Недавно я наткнулся на эту статью о том, как написать синглтон в Node.js. Я знаю , что в документации require
государств , что:
Модули кэшируются после первой загрузки. Многократные вызовы
require('foo')
не могут привести к многократному выполнению кода модуля.
Таким образом, кажется, что каждый требуемый модуль можно легко использовать как синглтон без шаблонного кода синглтона.
Вопрос:
Предоставляет ли вышеприведенная статья решение для создания синглтона?
Ответы:
В основном это связано с кешированием nodejs. Легко и просто.
https://nodejs.org/api/modules.html#modules_caching
(Версия 6.3.1)
Итак, простыми словами.
Если вам нужен синглтон; экспортировать объект .
Если вам не нужен синглтон; экспортировать функцию (и делать что-то / возвращать / что угодно в этой функции).
Чтобы быть ОЧЕНЬ ясным, если вы сделаете это правильно, это должно сработать, посмотрите https://stackoverflow.com/a/33746703/1137669 (ответ Аллена Люса). Он объясняет в коде, что происходит, когда кеширование не удается из-за другого разрешения имен файлов. Но если вы ВСЕГДА решаете использовать одно и то же имя файла, это должно работать.
Обновление 2016
создание настоящего синглтона в node.js с символами es6 Другое решение : по этой ссылке
Обновление 2020
Этот ответ относится к CommonJS (собственный способ Node.js для импорта / экспорта модулей). Node.js, скорее всего, переключится на модули ECMAScript : https://nodejs.org/api/esm.html (ECMAScript - настоящее имя JavaScript, если вы не знали)
При переходе на ECMAScript прочтите пока следующее: https://nodejs.org/api/esm.html#esm_writing_dual_packages_ while_avoiding_or_minimizing_hazards
источник
Все вышеперечисленное слишком сложно. Существует мнение, что шаблоны проектирования демонстрируют недостатки реального языка.
Языки с ООП на основе прототипов (бесклассовые) вообще не нуждаются в одноэлементном шаблоне. Вы просто создаете один объект (тонну) на лету, а затем используете его.
Что касается модулей в node, да, по умолчанию они кэшируются, но это можно настроить, например, если вы хотите горячую загрузку изменений модуля.
Но да, если вы хотите использовать общий объект повсюду, поместите его в экспорт модуля. Только не усложняйте это «одноэлементным шаблоном», он не нужен в JavaScript.
источник
There is a school of thought which says design patterns are showing deficiencies of actual language.
Нет. Когда кэширование модуля узла не удается, этот одноэлементный шаблон не работает. Я изменил пример, чтобы он работал в OSX:
Это дает результат, которого ожидал автор:
Но небольшая модификация отменяет кеширование. В OSX сделайте следующее:
Или в Linux:
Затем измените
sg2
строку require на:И бац , синглтон побежден:
Я не знаю приемлемого способа обойти это. Если вы действительно чувствуете необходимость сделать что-то одноэлементное и не против загрязнять глобальное пространство имен (и многие проблемы, которые могут возникнуть), вы можете изменить строки автора
getInstance()
иexports
на:Тем не менее, я никогда не сталкивался с ситуацией в производственной системе, когда мне нужно было бы сделать что-то подобное. Я также никогда не чувствовал необходимости использовать шаблон singleton в Javascript.
источник
Заглянем немного дальше в предупреждения о кешировании модулей в документации по модулям:
Итак, в зависимости от того, где вы находитесь, когда вам нужен модуль, можно получить другой экземпляр модуля.
Похоже, модули - не простое решение для создания синглтонов.
Изменить: Или, может быть, они есть . Как и @mkoryak, я не могу придумать случай, когда один файл может разрешаться для разных имен файлов (без использования символических ссылок). Но (как отмечает @JohnnyHK), несколько копий файла в разных
node_modules
каталогах будут загружаться и храниться отдельно.источник
node_modules
каждый из которых зависит от одного и того же модуля, но есть отдельные копии этого зависимого модуля вnode_modules
подкаталоге каждого из двух разных модулей.require('./db')
код находится в двух отдельных файлах, кодdb
модуля выполняется дваждыrequire('../lib/myModule.js');
в один файл иrequire('../lib/mymodule.js');
в другой, и он не доставил один и тот же объект.Подобный синглтон в node.js (или в JS браузера, если на то пошло) совершенно не нужен.
Поскольку модули кэшируются и сохраняют состояние, пример, приведенный в предоставленной вами ссылке, можно легко переписать гораздо проще:
источник
may not
Применяется приnpm link
других модулей в процессе разработки. Поэтому будьте осторожны при использовании модулей, которые полагаются на один экземпляр, например на eventBus.Единственный ответ здесь, который использует классы ES6
требуется этот синглтон с помощью:
Единственная проблема здесь в том, что вы не можете передавать параметры в конструктор класса, но это можно обойти, вручную вызвав
init
метод.источник
summary
в другом классе без его повторной инициализации?Для синглтона в js ничего особенного не нужно, код в статье с таким же успехом может быть:
Вне node.js (например, в браузере js) вам нужно добавить функцию-оболочку вручную (в node.js это делается автоматически):
источник
Синглтоны хороши в JS, просто они не должны быть такими многословными.
В узле, если вам нужен синглтон, например, для использования одного и того же экземпляра ORM / DB в различных файлах на уровне сервера, вы можете поместить ссылку в глобальную переменную.
Просто напишите модуль, который создает глобальную переменную, если она не существует, а затем возвращает ссылку на нее.
@ allen-luce был прав с его примером кода сноски, скопированным здесь:
но важно отметить, что использование
new
ключевого слова не требуется. Любой старый объект, функция, iife и т. Д. Будут работать - здесь нет ООП-вуду.бонусные баллы, если вы закроете некоторый объектный объект внутри функции, которая возвращает ссылку на него, и сделаете эту функцию глобальной - тогда даже переназначение глобальной переменной не повредит экземпляры, уже созданные из нее - хотя это сомнительно полезно.
источник
module.exports = new Foo()
потому что module.exports не будет выполняться снова, если вы не сделаете что-то действительно глупоеВсе просто.
foo.js
Тогда просто
источник