Шаг 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 приложения в браузере:
Вопрос решен. Есть иной, более вкусный вариант решения? Не стесняемся, делимся в комментах.









Комментариев нет:
Отправить комментарий
Комментарий будет опубликован после модерации