2011-06-09 25 views
6

node.js documentation regarding module caching,以下语句是由:Node.js - 模块缓存,部分完​​成对象和周期性依赖关系?

多次调用要求(“富”)可能不导致要多次执行该模块的代码。这是一个重要的功能。通过它,可以返回“部分完成”对象,从而允许传递依赖性被加载,即使它们会导致循环。

我对最后一句话有点困惑。什么是“部分完成”的对象?这与允许(或避免)周期性依赖关系有何关系?

回答

5

如果您require来自文件的一个包,并导致该包中的文件为require导致初始require的文件,那么您有一个循环依赖关系。默认情况下,它只是圈出去。为了防止这种情况发生,可以在原始require开始的位置保留一个标记,以便下一次该文件是require'd它将从该点开始而不是开始。这不是完美的,但在加载一个包的情况下,您通常只对出口感兴趣,并且在这种情况下效果很好。

我推迟a diff for node-browserify回到原始方法的“部分完成”出口。基本上,每次都是require'd它会检查出口量。如果有更多的出口,这意味着上次包装不完整,并且可能仍在处理中。如果没有新的导出(新旧计数相同),则表示包完成,并且可以被缓存,以便模块代码不会多次执行。因为它在浏览器中,所以无法控制执行流程,因此模块代码会部分重复(分步执行)直到完成。而我确信Node.js有更优雅的处理。

0

node.js documentation中提供了一个很好和清晰的示例。它更详细地阐述了“部分完成”对象和循环依赖关系。

当存在循环require()调用时,模块在返回时可能没有完成执行。

考虑这种情况:

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; 
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); 

当main.js负荷a.js,然后依次加载b.js. a.js那时,b.js会尝试加载a.js.为了防止无限循环,将a.js exports对象的未完成副本返回给b.js模块。然后b.js完成加载,并将其导出对象提供给a.js模块。

当main.js加载了两个模块时,它们都完成了。因而该程序的输出将是:

节点main.js

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