Переосмысление книги Эдди Османи «Паттерны для масштабируемых JavaScript-приложений»
Материал из support.qbpro.ru
Андрей Климов.
Спасибо команде переводчиков за их огромный труд. Сам перевод находится здесь
Итак, скорее всего будет не профессионально, но как есть. (А то сам забудешь и другие не вспомнят)
В главе 9 предложен клевый шаблон проектирования - фасад. Вот его скелет
var module = (function() {
var _private = {
i: 5,
get: function() {
console.log('Текущее значение:' + this.i);
},
set: function(val) {
this.i = val;
},
run: function() {
console.log('процесс запущен');
},
jump: function() {
console.log('резкое изменение');
}
};
return {
facade: function(args) {
_private.set(args.val);
_private.get();
if (args.run) {
_private.run();
}
}
}
}());
module.facade({run:true, val:10}); // Текущее значение: 10, процесс запущен
Попробуем его применить к практике. Напишу асинхронный модуль, который возвращает список всех файлов в директории и всех вложенных поддиректориях определенным расширением (.html).
Фасад для асинхронного рекурсивного чтения списка фалов в директории
Проверено nodejs 0.11.12 Debian wheezy x86_64
#!/usr/bin/env node
"use strict";
var fs = require('fs');
var path = require('path');
var util = require('util');
var this_module = (function () {
var _private = {
"__dirname": "/home/html_path",
"__extention": /\.html$/i,
"debug": false,
"result": [],
"reader": function (_dirname, extension, callback) {
var results = [];
var that = this;
fs.readdir(_dirname, function (err, list) {
if (err) return callback(err);
var pending = list.length;
if (!pending) return callback(null, results);
list.forEach(function (file) {
file = _dirname + '/' + file;
fs.stat(file, function (err, stat) {
if (stat && stat.isDirectory()) {
that.reader(file, extension, function (err, res) {
results = results.concat(res);
if (!--pending) callback(null, results);
});
} else {
/*выбираем файлы которые соответствуют рег выражению*/
/*если убрать это условие в массив попадут все файлы*/
if (extension.test(file)) {
results.push(file);
}
if (!--pending) callback(null, results);
}
});
});
});
},
"cbk": function (err, result) {
if (err) {
console.error(util.inspect(err));
return;
}
console.log(util.inspect(result));
return result;
},
"read": function (dir, ext) {
ext = ext || this.__extention;
dir = dir || this.__dirname;
this.reader(dir, ext, this.cbk);
}
};
return {
read_file_list: function (args) {
_private.read();
}
}
}());
this_module.read_file_list()
Замыкание остается в памяти до прекращения процесса. А если это не нужно. Например при запуске кода в виртуальной машине Nodejs. Переделаем фасад для этой цели.
#!/usr/bin/env node
"use strict";
var fs = require('fs');
var path = require('path');
var util = require('util');
var this_module = {
_private: {
"__dirname": "/home/html_path",
"__extention": /\.html$/i,
"debug": false,
"result": [],
"reader": function (_dirname, extension, callback) {
var results = [];
var that = this;
/*============================*/
fs.readdir(_dirname, function (err, list) {
if (err) return callback(err);
var pending = list.length;
if (!pending) return callback(null, results);
list.forEach(function (file) {
file = _dirname + '/' + file;
fs.stat(file, function (err, stat) {
if (stat && stat.isDirectory()) {
that.reader(file, extension, function (err, res) {
results = results.concat(res);
if (!--pending) callback(null, results);
});
} else {
/*выбираем файлы которые соответствуют рег выражению*/
/*если убрать это условие в массив попадут все файлы*/
if (extension.test(file)) {
results.push(file);
}
if (!--pending) callback(null, results);
}
});
});
});
/*============================*/
},
"cbk": function (err, result) {
if (err) {
console.error(util.inspect(err));
return;
}
console.log(util.inspect(result));
return result;
},
"read": function (dir, ext) {
ext = ext || this.__extention;
dir = dir || this.__dirname;
this.reader(dir, ext, this.cbk);
}
}
};
function ret() {
return this._private.read();
}
var bound = ret.bind(this_module);
exports.reader = bound;
Пример использования
#!/usr/bin/env node
"use strict";
var util = require('util');
var file_list_reader = require('./mod_async_file_list3').reader;
var file_list = file_list_reader();
console.log(file_list);
