Javascript Node.js-模块缓存、部分完成的对象和循环依赖关系?

Javascript Node.js-模块缓存、部分完成的对象和循环依赖关系?,javascript,node.js,dependency-management,Javascript,Node.js,Dependency Management,在报告中,作出以下声明: 多次调用require('foo')可能不会导致多次执行模块代码。这是一个重要特征。使用它,可以返回“部分完成”的对象,从而允许加载可传递的依赖项,即使它们会导致循环 我对最后一句话有点困惑。什么是“部分完成”对象?这与允许(或避免)循环依赖关系有何关系?如果需要文件中的一个包,并且导致该包中的一个文件需要导致初始需要的文件,则存在循环依赖关系。默认情况下,它只会循环运行。为了防止这种情况,可以在原始require开始的位置保留一个标记,以便下次该文件require时,

在报告中,作出以下声明:

多次调用require('foo')可能不会导致多次执行模块代码。这是一个重要特征。使用它,可以返回“部分完成”的对象,从而允许加载可传递的依赖项,即使它们会导致循环


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

如果
需要文件中的一个包,并且导致该包中的一个文件
需要
导致初始
需要
的文件,则存在循环依赖关系。默认情况下,它只会循环运行。为了防止这种情况,可以在原始
require
开始的位置保留一个标记,以便下次该文件
require
时,它将从该点开始,而不是从开始。它并非完美无瑕,但在加载包的情况下,您通常只对出口感兴趣,并且在这种情况下效果良好


我推迟了一段时间,以获得“部分完成”导出的原始方法。基本上,每次有东西需要时,它都会检查出口量。如果有更多的出口,这意味着包装上次是不完整的,可能仍在处理中。如果没有新的导出(新的和旧的计数相等),则表示包已完成,并且可以缓存,这样模块代码就不会执行多次。由于它位于浏览器中,因此无法控制执行流,因此模块代码将部分重复(分步重复),直到完成。然而,我确信Node.js的处理更加优雅。

中提供了一个很好且清晰的示例。它更清楚地说明了“部分完成”的对象和循环依赖关系

当存在循环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');
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');
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.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');
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');
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:

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');
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');
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时,a.js依次加载b.js。此时,b.js尝试加载a.js。为了防止无限循环,将a.js导出对象的未完成副本返回到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