简体   繁体   English

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

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

In the node.js documentation regarding module caching , the following statement is made:node.js 关于模块缓存的文档中,做了以下声明:

Multiple calls to require('foo') may not cause the module code to be executed multiple times.多次调用 require('foo') 可能不会导致模块代码被多次执行。 This is an important feature.这是一个重要的特点。 With it, " partially done " objects can be returned, thus allowing transitive dependencies to be loaded even when they would cause cycles.有了它,可以返回“部分完成”的对象,从而允许加载传递依赖项,即使它们会导致循环。

I'm a bit confused about the last sentence.我对最后一句话有点困惑。 What is a "partially done" object?什么是“部分完成”object? How does this relate to allowing (or avoiding) cyclical dependencies?这与允许(或避免)循环依赖有何关系?

If you require a package from a file, and that causes a file in that package to require the file that caused the initial require then you have a cyclic dependency.如果您require一个文件中的 package,并且这会导致该 package 中的文件require require文件,那么您就有一个循环依赖关系。 By default, it would just go in circles.默认情况下,它只是go 圆圈。 In order to prevent this, one can keep a marker where the original require started so that the next time that file is require 'd it will start from that point rather than the beginning.为了防止这种情况,可以在原始require开始的位置保留一个标记,以便下次该文件被require时,它将从该点开始,而不是从头开始。 It's not flawless, but in the case of loading a package you are generally only interested in the exports, and it works well in that case.它并非完美无缺,但在加载 package 的情况下,您通常只对导出感兴趣,并且在这种情况下效果很好。

I pushed a diff for node-browserify a while back for a primitive method of "partially done" exports.为 node-browserify 推送了一个差异,用于“部分完成”导出的原始方法。 Basically, each time something is require 'd it will check the amount of exports.基本上,每次require某些东西时,它都会检查出口量。 If there are more exports, it means the package was incomplete the last time, and could still be processing.如果有更多的出口,则意味着上次 package 不完整,可能仍在处理中。 If there are no new exports (the new and old count are equal), then it means the package is done, and can be cached so that the module code is not executed multiple times.如果没有新的导出(新旧计数相等),则说明package已经完成,可以缓存,这样模块代码就不会被多次执行。 Being that it is in the browser, there's no control over execution flow, and thus the module code would be repeated partially (in steps) until done.由于它在浏览器中,因此无法控制执行流程,因此模块代码将部分重复(逐步)直到完成。 Whereas I'm sure Node.js has more elegant handling.而我确信 Node.js 有更优雅的处理。

There is a nice and clear example provided in the node.js documentation .It sheds more light on "partially done" object and cyclic dependencies. node.js 文档中提供了一个很好且清晰的示例。它更清楚地说明了“部分完成”的 object 和循环依赖关系。

When there are circular require() calls, a module might not have finished executing when it is returned.当存在循环 require() 调用时,模块在返回时可能尚未完成执行。

Consider this situation:考虑这种情况:

a.js:一个.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: 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:主.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);

When main.js loads a.js, then a.js in turn loads b.js.当 main.js 加载 a.js 时,a.js 依次加载 b.js。 At that point, b.js tries to load a.js.此时,b.js 会尝试加载 a.js。 In order to prevent an infinite loop, an unfinished copy of the a.js exports object is returned to the b.js module.为了防止无限循环,a.js 导出 object 的未完成副本返回到 b.js 模块。 b.js then finishes loading, and its exports object is provided to the a.js module.然后 b.js 完成加载,并将其导出 object 提供给 a.js 模块。

By the time main.js has loaded both modules, they're both finished.当 main.js 加载了这两个模块时,它们都已经完成了。 The output of this program would thus be:因此,该程序的 output 将是:

node 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

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

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