219 votes

Comment gérer les dépendances cycliques dans Node.js ?

J'ai travaillé avec nodejs Ces derniers temps, je suis encore en train de me familiariser avec la module Je vous prie donc de m'excuser si cette question est évidente. J'ai besoin d'un code qui ressemble à peu près à ce qui suit :

a.js (le fichier principal exécuté avec node)

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.

Existe-t-il une manière correcte / meilleure de structurer modules pour obtenir ce que je veux ? Existe-t-il une meilleure façon de partager variables à travers modules ?

201voto

lanzz Points 19475

Essayez de définir les propriétés de module.exports au lieu de le remplacer complètement. Par exemple, module.exports.instance = new ClassA() en a.js , module.exports.ClassB = ClassB en b.js . Lorsque vous créez des dépendances circulaires entre modules, le module qui en a besoin reçoit une référence à un module incomplet. module.exports du module requis, auquel vous pouvez ajouter d'autres propriétés par la suite, mais lorsque vous définissez l'ensemble de l'élément module.exports vous créez en fait un nouvel objet auquel le module demandeur n'a aucun moyen d'accéder.

124voto

JohnnyHK Points 61191

Bien que node.js permette les require dépendances, comme vous l'avez constaté, il peut être assez désordonné et il est probablement préférable de restructurer votre code pour ne pas en avoir besoin. Créez peut-être une troisième classe qui utilise les deux autres pour accomplir ce dont vous avez besoin.

61voto

Will Stern Points 1727

[EDIT] nous ne sommes plus en 2015 et la plupart des bibliothèques (i.e. express) ont fait des mises à jour avec de meilleurs modèles et les dépendances circulaires ne sont donc plus nécessaires. Je recommande simplement ne pas les utiliser .


Je sais que je déterre une vieille réponse ici... Le problème est que module.exports est défini comme suit après vous avez besoin de la classe B. (ce que montre le lien de JohnnyHK) Les dépendances circulaires fonctionnent très bien en Node, elles sont juste définies de manière synchrone. Lorsqu'elles sont utilisées correctement, elles résolvent en fait beaucoup de problèmes communs à Node (comme l'accès à express.js app d'autres fichiers)

Assurez-vous simplement que les exportations nécessaires sont définies avant vous avez besoin d'un fichier avec une dépendance circulaire.

Cela va casser :

var ClassA = function(){};
var ClassB = require('classB'); //will require ClassA, which has no exports yet

module.exports = ClassA;

Cela fonctionnera :

var ClassA = module.exports = function(){};
var ClassB = require('classB');

J'utilise ce modèle tout le temps pour accéder à la base de données express.js app dans d'autres dossiers :

var express = require('express');
var app = module.exports = express();
// load in other dependencies, which can now require this file and use app

48voto

coen Points 508

Parfois, il est vraiment artificiel d'introduire une troisième classe (comme le conseille JohnnyHK), donc en plus de Ianzz : Si vous voulez remplacer le module.exports, par exemple si vous créez une classe (comme le fichier b.js dans l'exemple ci-dessus), c'est également possible, il suffit de s'assurer que dans le fichier qui démarre la circulaire require, la déclaration 'module.exports = ...' se trouve avant la déclaration require.

a.js (le fichier principal exécuté avec node)

var ClassB = require("./b");

var ClassA = function() {
    this.thing = new ClassB();
    this.property = 5;
}

var a = new ClassA();

module.exports = a;

b.js

var ClassB = function() {
}

ClassB.prototype.doSomethingLater() {
    util.log(a.property);
}

module.exports = ClassB;

var a = require("./a"); // <------ this is the only necessary change

16voto

Nicolas Gramlich Points 1920

La solution consiste à "déclarer" votre objet d'exportation avant d'exiger un autre contrôleur. Ainsi, si vous structurez tous vos modules de cette manière, vous ne rencontrerez aucun problème de ce type :

// Module exports forward declaration:
module.exports = {

};

// Controllers:
var other_module = require('./other_module');

// Functions:
var foo = function () {

};

// Module exports injects:
module.exports.foo = foo;

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X