Ich bin kürzlich auf diesen Artikel gestoßen, in dem es darum geht, einen Singleton in Node.js zu schreiben. Ich kenne die Dokumentation von require
Staaten , die:
Module werden nach dem ersten Laden zwischengespeichert. Bei mehreren Aufrufen von wird
require('foo')
der Modulcode möglicherweise nicht mehrmals ausgeführt.
Es scheint also, dass jedes erforderliche Modul ohne den Singleton-Boilerplate-Code problemlos als Singleton verwendet werden kann.
Frage:
Bietet der obige Artikel eine umfassende Lösung zum Erstellen eines Singletons?
javascript
node.js
design-patterns
singleton
mkoryak
quelle
quelle
Antworten:
Dies hat im Wesentlichen mit dem Zwischenspeichern von Knoten zu tun. Schlicht und einfach.
https://nodejs.org/api/modules.html#modules_caching
(v 6.3.1)
Also in einfachen Worten.
Wenn Sie einen Singleton wollen; ein Objekt exportieren .
Wenn Sie keinen Singleton wollen; exportiere eine Funktion (und mache Sachen / gib Sachen zurück / was auch immer in dieser Funktion).
Um ganz klar zu sein, wenn Sie dies richtig machen, sollte es funktionieren, schauen Sie unter https://stackoverflow.com/a/33746703/1137669 (Allen Luces Antwort). Im Code wird erklärt, was passiert, wenn das Caching aufgrund unterschiedlich aufgelöster Dateinamen fehlschlägt. Wenn Sie jedoch IMMER denselben Dateinamen verwenden, sollte dies funktionieren.
Update 2016
Erstellen eines echten Singletons in node.js mit es6-Symbolen Eine weitere Lösung : in diesem Link
Update 2020
Diese Antwort bezieht sich auf CommonJS (Node.js eigene Methode zum Importieren / Exportieren von Modulen). Node.js wird höchstwahrscheinlich auf ECMAScript-Module umsteigen : https://nodejs.org/api/esm.html (ECMAScript ist der wirkliche Name von JavaScript, wenn Sie es nicht wussten)
Lesen Sie bei der Migration zu ECMAScript vorerst Folgendes: https://nodejs.org/api/esm.html#esm_writing_dual_packages_while_avoiding_or_minimizing_hazards
quelle
All dies ist zu kompliziert. Es gibt eine Denkschule, die besagt, dass Designmuster Mängel der tatsächlichen Sprache aufweisen.
Sprachen mit prototypbasiertem OOP (klassenlos) benötigen überhaupt kein Singleton-Muster. Sie erstellen einfach ein einzelnes (Tonnen-) Objekt im laufenden Betrieb und verwenden es dann.
Ja, Module im Knoten werden standardmäßig zwischengespeichert, können jedoch optimiert werden, wenn Sie beispielsweise Moduländerungen im laufenden Betrieb laden möchten.
Aber ja, wenn Sie gemeinsam genutzte Objekte überall verwenden möchten, ist es in Ordnung, sie in einen Modulexport zu integrieren. Komplizieren Sie es einfach nicht mit "Singleton-Muster", es wird in JavaScript nicht benötigt.
quelle
There is a school of thought which says design patterns are showing deficiencies of actual language.
Nein. Wenn das Modul-Caching des Knotens fehlschlägt, schlägt dieses Singleton-Muster fehl. Ich habe das Beispiel so geändert, dass es unter OSX sinnvoll ausgeführt wird:
Dies gibt die vom Autor erwartete Ausgabe:
Eine kleine Modifikation verhindert jedoch das Caching. Gehen Sie unter OSX folgendermaßen vor:
Oder unter Linux:
Ändern Sie dann die
sg2
erforderliche Zeile in:Und bam , der Singleton ist besiegt:
Ich kenne keinen akzeptablen Weg, um das zu umgehen. Wenn Sie wirklich das Bedürfnis haben, etwas Singleton-ähnliches zu machen und den globalen Namespace (und die vielen Probleme, die daraus entstehen können) zu verschmutzen, können Sie den Autor
getInstance()
und dieexports
Zeilen ändern in:Trotzdem bin ich noch nie auf ein Produktionssystem gestoßen, in dem ich so etwas tun musste. Ich hatte auch nie das Bedürfnis, das Singleton-Muster in Javascript zu verwenden.
quelle
Sehen Sie sich die Vorsichtsmaßnahmen zum Zwischenspeichern von Modulen in den Moduldokumenten etwas genauer an:
Je nachdem, wo Sie sich befinden, wenn Sie ein Modul benötigen, können Sie eine andere Instanz des Moduls abrufen.
Klingt so, als wären Module keine einfache Lösung zum Erstellen von Singletons.
Edit: Oder vielleicht sind sie es . Wie bei @mkoryak kann ich keinen Fall finden, in dem eine einzelne Datei in verschiedene Dateinamen aufgelöst werden könnte (ohne Verwendung von Symlinks). Aber (wie @JohnnyHK kommentiert) werden mehrere Kopien einer Datei in verschiedenen
node_modules
Verzeichnissen jeweils separat geladen und gespeichert.quelle
node_modules
denen jedes vom selben Modul abhängt, aber es gibt separate Kopien dieses abhängigen Moduls imnode_modules
Unterverzeichnis jedes der beiden verschiedenen Module.require('./db')
ist in zwei separaten Dateien, der Code für dasdb
Modul wird zweimal ausgeführtrequire('../lib/myModule.js');
eine Datei und einerequire('../lib/mymodule.js');
andere aufgerufen und es wurde nicht das gleiche Objekt geliefert.Ein solcher Singleton in node.js (oder in Browser JS) ist völlig unnötig.
Da Module zwischengespeichert und statusbehaftet sind, könnte das Beispiel auf dem von Ihnen angegebenen Link viel einfacher umgeschrieben werden:
quelle
may not
gilt, wenn Sienpm link
andere Module während der Entwicklung. Seien Sie also vorsichtig, wenn Sie Module verwenden, die auf einer einzelnen Instanz basieren, z. B. einem eventBus.Die einzige Antwort hier, die ES6-Klassen verwendet
Benötigen Sie diesen Singleton mit:
Das einzige Problem hierbei ist, dass Sie keine Parameter an den Klassenkonstruktor übergeben können, dies kann jedoch durch manuelles Aufrufen einer
init
Methode umgangen werden .quelle
summary
in einer anderen Klasse verwenden, ohne sie erneut zu initialisieren?Sie brauchen nichts Besonderes, um einen Singleton in js zu erstellen. Der Code im Artikel könnte genauso gut sein:
Außerhalb von node.js (z. B. in Browser js) müssen Sie die Wrapper-Funktion manuell hinzufügen (dies erfolgt automatisch in node.js):
quelle
Singletons sind in JS in Ordnung, sie müssen einfach nicht so ausführlich sein.
Wenn Sie im Knoten einen Singleton benötigen, um beispielsweise dieselbe ORM / DB-Instanz für verschiedene Dateien in Ihrer Serverschicht zu verwenden, können Sie die Referenz in eine globale Variable einfügen.
Schreiben Sie einfach ein Modul, das die globale Variable erstellt, wenn sie nicht vorhanden ist, und geben Sie dann einen Verweis darauf zurück.
@ Allen-luce hatte es richtig mit seinem hier kopierten Fußnoten-Codebeispiel:
Es ist jedoch wichtig zu beachten, dass die Verwendung des
new
Schlüsselworts nicht erforderlich ist. Jedes alte Objekt, jede Funktion, jedes Leben usw. wird funktionieren - hier findet kein OOP-Voodoo statt.Bonuspunkte, wenn Sie ein Objekt in einer Funktion schließen, die einen Verweis darauf zurückgibt, und diese Funktion zu einer globalen Funktion machen - selbst eine Neuzuweisung der globalen Variablen wird die bereits daraus erstellten Instanzen nicht blockieren - obwohl dies fraglich nützlich ist.
quelle
module.exports = new Foo()
weil module.exports nicht erneut ausgeführt wird, es sei denn, Sie tun etwas wirklich DummesEinfach halten.
foo.js
Dann einfach
quelle