Comment traiter les dépendances cycliques dans Node.js
J'ai travaillé avec nodejs ces derniers temps et encore se familiariser avec le système de module alors, toutes mes excuses si c'est une question évidente. Je veux le code à peu près comme suit ci-dessous:
un.js (le principal de l'exécution du fichier avec nœud)
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;
Mon problème semble être que je ne peux pas accéder à l'instance de ClassA à partir d'une instance de ClassB.
Est-il une bonne /meilleure façon de structure des modules de réaliser ce que je veux?
Est-il une meilleure façon de partager des variables entre les modules?
- Je vous suggère de regarder dans une requête de commande de la séparation, de motif observable et puis ce que le CS gars gestionnaires d'appel - qui est en fait un wrapper pour le motif observable.
Vous devez vous connecter pour publier un commentaire.
Tout node.js ne permettent circulaire
require
dépendances, comme vous l'avez constaté, il peut être assez salissante et vous êtes probablement mieux de la restructuration de votre code afin de ne pas en avoir besoin. Peut-être la création d'une troisième classe qui utilise les deux autres pour accomplir ce que vous avez besoin.exports = {}
en haut de votre code, puisexports = yourData
à la fin de votre code. Avec cette pratique, vous permettra d'éviter presque toutes les erreurs de dépendances circulaires.Essayer de définir des propriétés sur
module.exports
, au lieu de la remplacer complètement. E. g.,module.exports.instance = new ClassA()
dansa.js
,module.exports.ClassB = ClassB
dansb.js
. Quand vous faites circulaire module de dépendances, le nécessitant module permettra d'obtenir une référence à un incomplètesmodule.exports
dans le module, vous pouvez ajouter d'autres propriétés de ce dernier, mais quand vous réglez la totalité de lamodule.exports
, vous créez un nouvel objet qui l'nécessitant le module n'a aucun moyen d'accès.module.exports
sans la remettre en place, pour permettre à d'autres classes de "construire" une instance de la classe?[EDIT] ce n'est pas 2015 et la plupart des bibliothèques (c'est à dire express) ont fait des mises à jour avec de meilleures habitudes afin de dépendances circulaires ne sont plus nécessaires. Je recommande simplement de ne pas les utiliser.
Je sais que je suis en train de déterrer un vieux de réponse ici...
Le problème ici est que le module.les exportations est défini après vous avez besoin de ClassB.
(qui JohnnyHK lien de la montre)
Les dépendances circulaires de l'excellent travail dans le Nœud, ils sont définis de manière synchrone.
Lorsqu'il est utilisé correctement, ils sont en fait de résoudre beaucoup de nœud commun des questions (comme un accès à express.js
app
à partir d'autres fichiers)Assurez-vous que votre nécessaire exportations sont définis avant vous avez besoin d'un fichier avec une dépendance circulaire.
Ce sera la rupture:
Cela fonctionne:
- Je utiliser ce modèle de tous les temps pour accéder à l'express.js
app
dans d'autres fichiers:Parfois, il est vraiment artificielle à introduire une troisième classe (comme JohnnyHK conseille), donc, en plus de Ianzz:
Si vous ne souhaitez remplacer le module.les exportations, par exemple si vous êtes à la création d'une classe (comme le b.fichier js dans l'exemple ci-dessus), c'est possible aussi, assurez-vous que le fichier est à partir de la circulaire de besoin, le module de l'.les exportations = ...' instruction qui se passe avant le besoin de l'instruction.
un.js (le principal de l'exécution du fichier avec nœud)
b.js
La solution est de déclarer avant " votre exportations de l'objet avant d'exiger tout autre contrôleur. Donc, si vous avez de la structure de tous vos modules comme cela et vous n'aurez pas de problèmes comme ça:
exports.foo = function() {...}
à la place. Certainement fait le tour. Merci!Une solution qui nécessitent peu de changement est l'extension de
module.exports
au lieu de passer outre.un.js - app point d'entrée et le module d'utiliser la méthode de b.js*
b.js - module qui utilisent la méthode de le faire à partir d'un.js
Il va travailler et produire:
Bien que ce code ne fonctionnera pas:
un.js
b.js
De sortie:
underscore
, puis ES6 duObject.assign()
peut faire le même travail que_.extend()
est en train de faire dans cette réponse.Qu'en est paresseux, nécessitant seulement lorsque vous en avez besoin? Si votre b.js se présente comme suit
Bien sûr, il est de bonne pratique de mettre toutes exiger des déclarations au début du fichier. Mais il y sont reprises, où je me pardonne pour sélectionner quelque chose de un aucun lien avec ce module. Appeler un hack, mais parfois c'est mieux que d'introduire une nouvelle dépendance, ou l'ajout d'un module supplémentaire ou l'ajout de nouvelles structures (EventEmitter, etc)
Une autre méthode que j'ai vu des gens faire est d'exporter à la première ligne et de l'enregistrer dans une variable locale comme ceci:
J'ai tendance à utiliser cette méthode, connaissez-vous tous les inconvénients de celui-ci?
Vous pouvez résoudre ce problème facilement: il suffit d'exporter vos données avant de vous besoin de quelque chose d'autre dans les modules où vous utilisez le module.exportations:
classA.js
classB.js
En fait j'ai fini par demander mon dépendance avec
pas assez, mais il fonctionne. Il est plus compréhensible et plus honnête que de changer de b.js (par exemple, seulement en augmentant les modules.à l'exportation), qui, autrement, est parfait comme il est.
Similaire à lanzz et setect réponses, j'ai été en utilisant le modèle suivant:
La
Object.assign()
copies membres dans lesexports
objet qui a déjà été donné à d'autres modules.La
=
affectation est logiquement redondant, car il est tout simplement la mise enmodule.exports
à lui-même, mais je l'utilise parce qu'il aide mon IDE (WebStorm) à reconnaître quefirstMember
est une propriété de ce module, donc "Aller -> Déclaration" (Cmd-B) et de l'outillage d'autres vont travailler à partir d'autres fichiers.Ce modèle n'est pas très jolie, donc je ne l'utilise que quand une dépendance cyclique question doit être résolue.
Voici une rapide solution de contournement que j'ai trouvé l'utilisation complète.
Sur fichier.js'
Sur le fichier 'b.js' écrire la suite de
De cette façon sur la prochaine itération de la boucle d'événement de classes seront correctement définis et ceux qui nécessitent des déclarations fonctionnera comme prévu.