Шаг 1. Экспортируем объект. Cоздаем приложение - app.js, а также импортируемый в него модуль - singleton.js:
app.js
var a; for (var i = 1; i < 4; i += 1) { a = 'a' + i; module[a] = require('./singleton'); console.log('counter: %d', module[a].counter); }
singleton.js
var i = 0; module.exports = { counter: ++i };
Выполняем приложение:
Очевидно все три раза у нас один и тот же объект. Тот же результат получаем если экспортируем объект с помощью конструктора:
singleton.js
var i = 0; module.exports = new Singleton(); function Singleton() { this.counter = ++i; };
Шаг 2. Добавляем в конструктор аргумент:
app.js
var a; for (var i = 1; i < 4; i += 1) { a = 'a' + i; module[a] = require('./singleton')({prop: i}); console.log('prop: %d, counter: %d', module[a].prop, module[a].counter); }
singleton.js
var i = 0; module.exports = function(config) { return { prop: config.prop, counter: ++i }; };
Выполняем:
В результате у нас три разных объекта, которые кстати можно создать и более традиционным способом:app.js
var A, a; for (var i = 1; i < 4; i += 1) { a = 'a' + i; A = require('./singleton'); module[a] = new A({prop: i}); console.log('prop: %d, counter: %d', module[a].prop, module[a].counter); }
Как правило я использую иную конструкцию для экспорта конструктора:
singleton.js
var i = 0; module.exports = function Singleton(config) { if (!(this instanceof Singleton)) return new Singleton(config); this.prop = config.prop; this.counter = ++i; };
Импортируем модуль в приложение еще раз с одним из аргументов, переданных конструктору ранее:
app.js
var a; for (var i = 1; i < 4; i += 1) { a = 'a' + i; module[a] = require('./singleton')({prop: i}); console.log('prop: %d, counter: %d', module[a].prop, module[a].counter); } var b = require('./singleton')({prop: 1}); console.log('prop: %d, counter: %d', b.prop, b.counter);
И в результате у нас четыре объекта, а хотелось бы три.
Шаг 3. Применяем шаблон singleton:
singleton.js
var i = 0; var singleton = {}; module.exports = function Singleton(config) { if (singleton[config.prop]) return singleton[config.prop]; if (!(this instanceof Singleton)) return singleton[config.prop] = new Singleton(config); this.prop = config.prop; this.counter = ++i; };
Вот теперь все в елочку:
Шаг 4. Применяем шаблон singleton для использования подключения к MongoDB. Создадим еще один модуль по имени db.js:
var Db = require('mongodb').Db; var Server = require('mongodb').Server; var connection; module.exports = function(cb) { if (connection) return cb(connection); var db = new Db('test', new Server('127.0.0.1', 27017, { auto_reconnect: true }), {w: 'majority', safe: true}); db.open(function(err, db) { if (err) throw err; connection = db; cb(db); }); };
Импортируем модуль в приложение:
app.js
require('./db')(function(db) { db.collection('test').findOne({}, function(err, item) { if (err) throw err; console.dir(item); }); });
Выполняем приложение и получаем документ коллекции test базы данных test:
Шаг 5. Импортируем модуль подключения к базе данных в модуль singleton:
singleton.js
var i = 0; var singleton = {}; module.exports = function Singleton(config, cb) { if (singleton[config.prop]) return singleton[config.prop]; if (!(this instanceof Singleton)) return singleton[config.prop] = new Singleton(config, cb); this.prop = config.prop; this.counter = ++i; require('./db')(function(db) { this.findOne = function(cb) { db.collection('test').findOne({}, {_id: 0}, cb); }; cb(); }.bind(this)); };
Вызываем модуль singleton в приложении три раза, два из которых с одинаковым аргументом:
app.js
var c = require('./singleton')({prop: 1}, function() { console.log('prop: %d, counter: %d', c.prop, c.counter); c.findOne(function(err, item) { if (err) throw err; console.log(item); }); }); var d = require('./singleton')({prop: 1}, function() { console.log('prop: %d, counter: %d', d.prop, d.counter); d.findOne(function(err, item) { if (err) throw err; console.log(item); }); }); var e = require('./singleton')({prop: 2}, function() { console.log('prop: %d, counter: %d', e.prop, e.counter); e.findOne(function(err, item) { if (err) throw err; console.log(item); }); });
Выполняем приложение:
Не смотря на то, что мы трижды создали объект, экспортируемый модулем singleton, в результате у нас в памяти два объекта, что и требовалось.
Шаг 6. Используем модули в веб-приложении.
Модуль app отправляет в модуль singleton в качастве аргумента имя коллекции:
app.js
var model = require('./singleton')({prop: 'test'}, function() { console.log('prop: %s, counter: %d', model.prop, model.counter); require('http').createServer(function (req, res) { model.findOne(function(err, item) { if (err) res.end(JSON.stringify({err: err.message})); res.end(JSON.stringify(item)); }); }).listen(1337, '127.0.0.1'); console.log('Magic happens at http://127.0.0.1:1337/'); });
Модуль singleton асинхронно получает объект подключения к базе данных, после чего асинхронно же возвращает метод findOne, который в свою очередь использует полученное подключение для извлечения одного документа коллекции базы данныз test:
singleton.js
var singleton = {}; module.exports = function Singleton(config, cb) { if (singleton[config.prop]) return singleton[config.prop]; if (!(this instanceof Singleton)) return singleton[config.prop] = new Singleton(config, cb); this.prop = config.prop; this.counter = ++i; require('./db')(function(db) { this.findOne = function(cb) { db.collection(this.prop).findOne({}, {_id: 0}, cb); }; cb(); }.bind(this)); };
Запускаем приложение:
Открываем URL приложения в браузере:
Вопрос решен. Есть иной, более вкусный вариант решения? Не стесняемся, делимся в комментах.
Комментариев нет:
Отправить комментарий
Комментарий будет опубликован после модерации