繁体   English   中英

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

[英]Node.js - module caching, partially done objects, and cyclical dependencies?

node.js 关于模块缓存的文档中,做了以下声明:

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

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

如果您require一个文件中的 package,并且这会导致该 package 中的文件require require文件,那么您就有一个循环依赖关系。 默认情况下,它只是go 圆圈。 为了防止这种情况,可以在原始require开始的位置保留一个标记,以便下次该文件被require时,它将从该点开始,而不是从头开始。 它并非完美无缺,但在加载 package 的情况下,您通常只对导出感兴趣,并且在这种情况下效果很好。

为 node-browserify 推送了一个差异,用于“部分完成”导出的原始方法。 基本上,每次require某些东西时,它都会检查出口量。 如果有更多的出口,则意味着上次 package 不完整,可能仍在处理中。 如果没有新的导出(新旧计数相等),则说明package已经完成,可以缓存,这样模块代码就不会被多次执行。 由于它在浏览器中,因此无法控制执行流程,因此模块代码将部分重复(逐步)直到完成。 而我确信 Node.js 有更优雅的处理。

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

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

考虑这种情况:

一个.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');

主.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 时,a.js 依次加载 b.js。 此时,b.js 会尝试加载 a.js。 为了防止无限循环,a.js 导出 object 的未完成副本返回到 b.js 模块。 然后 b.js 完成加载,并将其导出 object 提供给 a.js 模块。

当 main.js 加载了这两个模块时,它们都已经完成了。 因此,该程序的 output 将是:

节点 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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM