2016-08-07 1 views
3

У меня возникла проблема с доступом к полю в объекте, который требуется/импортирован в начале файла, однако это поле доступно при импорте объекта в более поздняя точка в коде.NodeJS: Раннее требование не имеет доступа к полю объекта


Я сделал небольшой пример, чтобы показать, что я имею в виду: [Execute code on CodingGround]

main.js:

var ClassA = require('./ClassA'); 

ClassA.init(); 

ClassA.js:

var ClassB = require('./ClassB'); 

var ClassA = function() {}; 

ClassA.init = function() { 
    // Define a variable in ClassA 
    this.myVar = 'My Value'; 

    // Create an instance of ClassB, and try to print the defined variable 
    var myClass = new ClassB(); 
    myClass.printMyVar(); 
}; 

module.exports = ClassA; 

ClassB.js:

var ClassA = require('./ClassA'); 

var ClassB = function() {}; 

ClassB.prototype.printMyVar = function() { 
    // Print the variable (not working) 
    console.log('My Var: ' + ClassA.myVar); 

    // Require ClassA again 
    ClassA = require('./ClassA'); 

    // Print the variable again (working) 
    console.log('My Var (again): ' + ClassA.myVar); 
}; 

module.exports = ClassB; 

я получаю следующий результат, когда main.js выполняется:

My Var: undefined 
My Var (again): My Value 

Почему первая строка покажет переменная не определена, и почему это показать правильно ли после повторного запроса/импорта объекта?

Это связано с круговой зависимостью, и если да, то как я могу избежать этой проблемы в будущем?

ответ

1

Описанная ситуация in the NodeJS modules "cycle" topic. Решение похоже на дополнение объект exports вместо заменяет его, если имеются круговые зависимости.

Вот их пример, модифицирована, чтобы показать, что, когда b проверяет a.doneпозже, он видит правильное значение:

a.js:

console.log('a starting'); 
exports.done = false; 
const b = require('./b.js'); 
console.log('in a, b.done = %j', b.done); 
exports.done = true; 
console.log('a done'); 

b.js:

console.log('b starting'); 
exports.done = false; 
const a = require('./a.js'); 
console.log('in b, a.done = %j', a.done); 
exports.done = true; 
exports.check = function() { 
    console.log('in b\'s check function, a.done = %j', a.done); 
}; 
console.log('b done'); 

main.js:

console.log('main starting'); 
const a = require('./a.js'); 
const b = require('./b.js'); 
console.log('in main, a.done=%j, b.done=%j', a.done, b.done); 
b.check(); 

Выход:

 
main starting 
a starting 
b starting 
in b, a.done = false 
b done 
in a, b.done = true 
a done 
in main, a.done=true, b.done=true 
in b's check function, a.done = true 
+0

Спасибо, что очень полезно. Я предполагаю, что вы подразумеваете, что я должен _add_ функции/поля в 'module.exports' вместо полной замены его, например' ClassA'. Если это так, как бы вы определили конструктор класса? Я задал аналогичный вопрос в этом комментарии: http://stackoverflow.com/questions/10869276/how-to-deal-with-cyclic-dependencies-in-node-js#comment64995389_10872988 –

+1

@ TimVisée: Я думаю, что очень что делает сам NodeJS в некоторых случаях: модуль определяет «пространство имен», если вы захотите (объект «export»), а отдельные классы доступны как свойства этого объекта, а не являются верхним уровнем. Например, например, 'fs.FSWatcher',' fs.Stats' и т. Д.Но они несовместимы: модуль событий заменяет объект 'export' на' EventEmitter'. (Я подозреваю, что модули ES2015 разрешат это, но это может быть принятие желаемого за действительное с моей стороны ...) –

+0

Спасибо. Я думаю, что я должен стараться избегать круговых зависимостей, чтобы сохранить все, кроме modulair_. –

Смежные вопросы