2016-08-07 30 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本身在某些情況下所做的那樣:模塊定義了一個「命名空間」(如果你願意的話)('exports'對象),並且單個類可以作爲該對象的屬性而不是頂層。例如,像'fs.FSWatcher','fs.Stats'等。但它們不一致:事件模塊用'EventEmitter'替換'exports'對象。 (我懷疑ES2015的模塊會解決這個問題,但這可能是我的一廂情願的想法......) –

+0

謝謝。 我想我應該儘量避免所有的循環依賴,以保持一切_modulair_。 –