обычно мы могли бы создать простой одноэлементный объект, например, с помощью Node.js:
var foo = {};
module.exports = foo;
or
function Foo(){}
module.exports = new Foo();
Однако
Каков наилучший способ сделать чистый одноэлементный модуль, которому для инициализации требуется внешняя переменная? В итоге делаю что-то вроде этого:
var value = null;
function init(val){
if(value === null){
value = val;
}
return value;
}
module.exports = init;
таким образом кто-то, использующий модуль, может передать значение инициализации для определенной переменной. Другой способ сделать это будет выглядеть так:
function Baz(value){
this.value = value;
}
var instance = null;
module.exports = function init(value){
if(instance === null){
instance = new Baz(value);
}
return instance;
}
есть две проблемы, с которыми я сталкиваюсь:
(1) это незначительно, но семантика неверна. Мы можем переименовать init в getInstance, но мы не можем сделать литерал одной и той же функции означающим «инициализировать и получить», поскольку это разные значения. Итак, у нас должна быть функция, которая делает две разные вещи. Создайте экземпляр и извлеките экземпляр. Мне это не нравится, особенно потому, что в некоторых случаях нам нужно убедиться, что аргумент для инициализации экземпляра не равен нулю. Когда несколько разработчиков используют модуль, неясно, был ли модуль уже инициализирован, и если они передают undefined в модуль, который не был инициализирован, это может стать проблемой или, по крайней мере, просто запутать.
(2) это важнее - в некоторых случаях инициализация Baz происходит асинхронно. Например, создание соединения Redis или чтение из файла для инициализации синглтона или создание соединения socket.io. Это то, что меня действительно сбивает с толку.
например вот модуль, который у меня есть, который я считаю действительно уродливым, который хранит соединение socket.io:
var io = null;
var init = function ($io) {
if (io === null) {
io = $io;
io.on('connection', function (socket) {
socket.on('disconnect', function () {
});
});
}
return io;
};
module.exports = {
getSocketIOConn: init
};
вышеуказанный модуль инициализируется так:
var server = http.createServer(app);
var io = socketio.listen(server);
require('../controllers/socketio.js').getSocketIOConn(io);
Поэтому я ищу шаблон проектирования, который позволит нам создать одноэлементный модуль, в котором процесс инициализации будет асинхронным. В идеале у нас не будет одной и той же функции как для инициализации экземпляра, так и для его извлечения. Существует ли такая вещь?
Я не думаю, что обязательно есть способ создать шаблон, решающий эту проблему, но, возможно, я совершаю ошибку, структурируя свой код таким образом, что создается проблема, которая не должна существовать - проблема инициализации модуль со значением только один раз, но с использованием одной функции как для инициализации экземпляра, так и для извлечения экземпляра.