Node 模块循环引用问题

摘要:
为了防止无限循环,请将a.jsexports对象的未完成副本返回到b.js模块。然后b.js完成加载并将其导出的对象提供给.js模块。再见。js加载了两个模块,它们都重新完成了。这个程序的输出将是:此时,主要。js完成两个模块的加载。程序的最终输出如下:$nodemain。jsmainstartingstartingstartingab,a.done=falsebdoneina,b.done=trueadoneinmain,a.done=true,b.done=true需要谨慎规划,以允许循环模块依赖项在应用程序中正确工作。应仔细设计模块,以便循环模块依赖性在程序中正常工作。通常,在循环引用之后,您最终会遇到未定义的,因为它不是代码中间部分的导出值。导入时,它将仅是未定义的。写到这里,我发现Node的官方网站已经有中英文双语版本。然而,我想记住这一点。

写作背景

循环引用是模块系统里一个避免不了的话题,可以加以讨论

Cycles

When there are circular require() calls, a module might not have finished executing when it is returned.

当在代码中出现循环 require 引用时,模块可能不会在返回结果前结束执行

Consider this situation:

考虑这个情景:

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

When main.js loads a.js, then a.js in turn loads b.js. At that point, b.js tries to load 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. b.js then finishes loading, and its exports object is provided to the a.js module.

当 main.js 加载 a.js 时,a.js 依次加载 b.js。这时,b.js 试图加载 a.js。为了防止无限循环,将 a.js exports 对象的未完成副本返回给 b.js 模块(就是 const b = require('./b.js'); 的上面那行 exports.down = false;)。 然后 b.js 完成加载,并将其导出对象提供给 a.js 模块。

By the time main.js has loaded both modules, they're both finished. The output of this program would thus be:

此时 main.js 完成对这两个模块的加载,最后程序的输出如下:

$ node 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

Careful planning is required to allow cyclic module dependencies to work correctly within an application.

要小心设计模块,来使得循环模块依赖项能在程序里正常工作。

通常循环引用后最后碰上 undefined,因为它并不会在代码中段 exports 值,import 的时候就只会是 undefined。

总结

总的来说,循环依赖的陷阱并不大容易出现,但一旦出现了,对于新手来说还真不好定位。它的存在给我们提了个醒,要时刻注意你项目的依赖关系不要过于复杂,哪天你发现一个你明明已经 exports 了的方法报 undefined is not a function,那就该警醒。

写到这里才发现原来 Node 官网早已经有了中英文对照版本,不过我还是为文一记吧。

免责声明:文章转载自《Node 模块循环引用问题》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇TP框架基础ArcGIS Server管理工具之批量发布动态地图服务工具.md下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Node版本的升级和降级

在开发的工程中,我们可能需要经常切换node版本来应对不同的开发环境,所以需要经常使用不同版本的node 一、安装npm插件n ,通过n模块来管理node版本1、全局安装n模块npm instlal -g n2、安装当前稳定版本n stable或者sudo n stable3、安装最新版本的n latest或者sudo n latest4、安装指定版本的n...

使用nvm管理node不同版本,安装,环境配置,切换不同版本的node版本

文章包含以下内容: 一、下载地址 二、nvm-noinstall.zip安装 三、nvm-setup.zip安装 四、测试安装以及使用 一、下载地址 https://github.com/coreybutler/nvm-windows/releases 二、nvm-noinstall.zip安装 1、把nvm_noinstall.zip解压到比如c:/de...

TS的tsconfig.json配置

一切教程以官方文档为准   初始化一个tsconfig.json配置文件tsc --init 信息配置信息: { "compilerOptions": { // "incremental": true, // 增置编译 // "tsBuildlnfoFile": "./buildFile",...

Jenkins 远程启动nodejs失败,使用pm2守护Nodejs

一、概述 使用Jenkins 远程ssh到linux,使用命令: ssh root@192.168.10.1 'cd /data/test;nohup npm start &' 发现linux服务器的node进程没有启动。但是本地执行命令: cd /data/test;nohup npm start &  是可以启动的。 具体原因,参考链接...

ElasticSearch基本学习

ES介绍 维基百科使用Elasticsearch来进行全文搜做并高亮显示关键词,以及提供search-as-you-type、did-you-mean等搜索建议功能。 英国卫报使用Elasticsearch来处理访客日志,以便能将公众对不同文章的反应实时地反馈给各位编辑。 StackOverflow将全文搜索与地理位置和相关信息进行结合,以提供more-l...

使用Docker构建redis集群--最靠谱的版本

1集群结构说明 集群中有三个主节点,三个从节点,一共六个结点。因此要构建六个redis的docker容器。在宿主机中将这六个独立的redis结点关联成一个redis集群。需要用到官方提供的ruby脚本。 2构建redis基础镜像 本文选择版本为redis-3.0.7,如果需要其他版本,直接修改wget后面地址中的版本号即可。 代码清单2-1 下载&...