Переосмысление книги Эдди Османи «Паттерны для масштабируемых JavaScript-приложений»
Материал из support.qbpro.ru
Версия от 22:20, 1 апреля 2014; imported>Supportadmin (→Фасад для асинхронного рекурсивного чтения списка фалов в директории)
Андрей Климов.
Спасибо команде переводчиков за их огромный труд. Сам перевод находится здесь
Итак, скорее всего будет не профессионально, но как есть. (А то сам забудешь и другие не вспомнят)
В главе 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); }, i: 5, get: function () { console.log('Текущее значение:' + this.i); }, set: function (val) { this.i = val; }, run: function () { console.log('процесс запущен'); }, jump: function () { console.log('резкое изменение'); } }; 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/kleem-head/THE_SYSTEM/new-nixtech/templates", "__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;