Ich habe in letzter Zeit mit NodeJS gearbeitet und mich immer noch mit dem Modulsystem auseinandergesetzt. Ich entschuldige mich, wenn dies eine offensichtliche Frage ist. Ich möchte Code ungefähr wie folgt:
a.js (die Hauptdatei, die mit dem Knoten ausgeführt wird)
var ClassB = require("./b");
var ClassA = function() {
this.thing = new ClassB();
this.property = 5;
}
var a = new ClassA();
module.exports = a;
b.js.
var a = require("./a");
var ClassB = function() {
}
ClassB.prototype.doSomethingLater() {
util.log(a.property);
}
module.exports = ClassB;
Mein Problem scheint zu sein, dass ich innerhalb einer Instanz von ClassB nicht auf die Instanz von ClassA zugreifen kann.
Gibt es eine korrekte / bessere Möglichkeit, Module zu strukturieren, um das zu erreichen, was ich will? Gibt es eine bessere Möglichkeit, Variablen zwischen Modulen auszutauschen?
Antworten:
Während node.js zirkuläre
require
Abhängigkeiten zulässt , kann es, wie Sie festgestellt haben, ziemlich chaotisch sein und Sie sollten Ihren Code wahrscheinlich besser umstrukturieren, um ihn nicht zu benötigen. Erstellen Sie möglicherweise eine dritte Klasse, die die beiden anderen verwendet, um das zu erreichen, was Sie benötigen.quelle
exports = {}
oben in Ihrem Code und dannexports = yourData
am Ende Ihres Codes ein hinzufügen . Mit dieser Vorgehensweise vermeiden Sie fast alle Fehler aus zirkulären Abhängigkeiten.Versuchen Sie, Eigenschaften festzulegen
module.exports
, anstatt sie vollständig zu ersetzen. ZBmodule.exports.instance = new ClassA()
ina.js
,module.exports.ClassB = ClassB
inb.js
. Wenn Sie kreisförmige Modulabhängigkeiten erstellen, erhält das erforderliche Modul einen Verweis auf ein unvollständigesmodule.exports
Modul aus dem erforderlichen Modul, zu dem Sie andere Eigenschaften hinzufügen können. Wenn Sie jedoch das gesamtemodule.exports
Modul festlegen , erstellen Sie tatsächlich ein neues Objekt, das das erforderliche Modul nicht hat Weg zum Zugang.quelle
module.exports
ohne ihn vollständig zu ersetzen, damit andere Klassen eine Instanz der Klasse "konstruieren" können?[BEARBEITEN] Es ist nicht 2015 und die meisten Bibliotheken (dh Express) haben Aktualisierungen mit besseren Mustern vorgenommen, sodass zirkuläre Abhängigkeiten nicht mehr erforderlich sind. Ich empfehle sie einfach nicht zu benutzen .
Ich weiß, dass ich hier eine alte Antwort ausgrabe ... Das Problem hier ist, dass module.exports definiert wird, nachdem Sie ClassB benötigen. (der Link von JohnnyHK zeigt) Zirkuläre Abhängigkeiten funktionieren in Node hervorragend, sie werden nur synchron definiert. Bei richtiger Verwendung lösen sie tatsächlich viele häufig auftretende Knotenprobleme (z. B. den Zugriff auf express.js
app
aus anderen Dateien).Stellen Sie einfach sicher, dass Ihre erforderlichen Exporte definiert sind, bevor Sie eine Datei mit einer zirkulären Abhängigkeit benötigen.
Dies wird brechen:
Das wird funktionieren:
Ich benutze dieses Muster ständig für den Zugriff auf die
app
Datei express.js in anderen Dateien:quelle
app = express()
Manchmal ist es wirklich künstlich, eine dritte Klasse einzuführen (wie JohnnyHK empfiehlt), also zusätzlich zu Ianzz: Wenn Sie die module.exports ersetzen möchten, zum Beispiel, wenn Sie eine Klasse erstellen (wie die Datei b.js in Im obigen Beispiel ist dies ebenfalls möglich. Stellen Sie einfach sicher, dass in der Datei, in der das Rundschreiben erforderlich ist, die Anweisung 'module.exports = ...' vor der Anweisung require ausgeführt wird.
a.js (die Hauptdatei, die mit dem Knoten ausgeführt wird)
b.js.
quelle
Die Lösung besteht darin, Ihr Exportobjekt weiterzuleiten, bevor Sie einen anderen Controller benötigen. Wenn Sie also alle Ihre Module so strukturieren und auf solche Probleme nicht stoßen:
quelle
exports.foo = function() {...}
stattdessen einfach zu verwenden . Auf jeden Fall den Trick gemacht. Vielen Dank!module.exports
ist standardmäßig bereits ein einfaches Objekt, daher ist Ihre Zeile "Vorwärtsdeklaration" redundant.Eine Lösung, die nur minimale Änderungen erfordert, wird erweitert,
module.exports
anstatt sie zu überschreiben.a.js - App-Einstiegspunkt und Modul, die die Methode do von b.js * verwenden
b.js - Modul, das die Methode do von a.js verwendet
Es wird funktionieren und produzieren:
Während dieser Code nicht funktioniert:
a.js
b.js.
Ausgabe:
quelle
underscore
Fall ist,Object.assign()
können ES6 die gleiche Arbeit leisten wie_.extend()
in dieser Antwort.Was ist mit faulen Anforderungen nur, wenn Sie müssen? Ihr b.js sieht also wie folgt aus
Natürlich ist es empfehlenswert, alle erforderlichen Anweisungen über die Datei zu setzen. Aber es gibt Fälle, in denen ich mir vergebe, etwas aus einem ansonsten nicht verwandten Modul herausgesucht zu haben. Nennen wir es einen Hack, aber manchmal ist dies besser, als eine weitere Abhängigkeit einzuführen oder ein zusätzliches Modul hinzuzufügen oder neue Strukturen hinzuzufügen (EventEmitter usw.)
quelle
Eine andere Methode, die ich gesehen habe, ist das Exportieren in der ersten Zeile und das Speichern als lokale Variable wie folgt:
Ich neige dazu, diese Methode zu verwenden. Kennen Sie die Nachteile?
quelle
module.exports.func1 =
,module.exports.func2 =
Sie können dies einfach lösen: Exportieren Sie einfach Ihre Daten, bevor Sie etwas anderes in Modulen benötigen, in denen Sie module.exports verwenden:
classA.js
classB.js
quelle
Ähnlich wie bei den Antworten von Lanzz und Setect habe ich das folgende Muster verwendet:
Das
Object.assign()
kopiert die Mitglieder in dasexports
Objekt, das bereits anderen Modulen übergeben wurde.Die
=
Zuweisung ist logisch redundant, da sie nurmodule.exports
auf sich selbst festgelegt wird. Ich verwende sie jedoch, weil sie meiner IDE (WebStorm) hilft, zu erkennen, dass diesfirstMember
eine Eigenschaft dieses Moduls ist. "Gehe zu -> Deklaration" (Cmd-B) und andere Werkzeuge funktionieren mit anderen Dateien.Dieses Muster ist nicht sehr hübsch, daher verwende ich es nur, wenn ein zyklisches Abhängigkeitsproblem behoben werden muss.
quelle
Hier ist eine schnelle Problemumgehung, die ich als vollwertig empfunden habe.
In der Datei 'a.js'
Schreiben Sie in die Datei 'b.js' Folgendes
Auf diese Weise werden bei der nächsten Iteration der Ereignisschleifenklassen korrekt definiert und die erforderlichen Anweisungen funktionieren wie erwartet.
quelle
Eigentlich brauchte ich meine Abhängigkeit von
nicht schön, aber es funktioniert. Es ist verständlicher und ehrlicher als das Ändern von b.js (zum Beispiel nur das Erweitern von modules.export), was ansonsten so wie es ist perfekt ist.
quelle
Eine Möglichkeit, dies zu vermeiden, besteht darin, keine Datei in einer anderen zu benötigen. Übergeben Sie sie einfach als Argument an eine Funktion, was auch immer Sie in einer anderen Datei benötigen. Auf diese Weise entsteht niemals eine zirkuläre Abhängigkeit.
quelle