Node.js循环依赖如何工作?为何导出的变量值无法同步更新?
问题原因
- CommonJS 模块的导出是值的拷贝,你导出的
x是基本类型(Number),模块初始化导出的时候就已经把初始值1复制到导出对象里了,后续你在test1.js里修改x变量,不会同步修改导出对象里的x属性,所以test2.js拿到的永远是初始值。 - 删除模块缓存的操作会导致每次重新require test1.js时,都完整执行一遍test1.js的代码,里面的
setInterval会重复注册,自然每秒输出的日志越来越多,而且每次重新执行test1.js都会重新把x赋值为1,自然拿不到正确的更新值。 - 你的代码本身存在循环引用(test1引用test2,test2又引用test1),本身也属于不推荐的写法,会额外增加逻辑复杂度。
推荐解决方案
方案1:用引用类型承载共享状态(适合多变量批量共享)
引用类型的导出是传递内存地址,修改属性会同步到所有引用方,不需要额外操作:
改后test1.js代码:
const { doStuff } = require("./test2.js"); // 所有要共享的变量统一放到state对象里 const state = { x: 1 }; setInterval(() => { console.log("Test1 :", state.x); state.x++; doStuff(); }, 1000); // 导出整个引用类型的state对象 module.exports = { state };
改后test2.js代码:
module.exports = { doStuff(){ const { state } = require("./test1.js"); console.log("Test2 :", state.x); }, };
方案2:参数传递(最推荐,耦合度最低)
直接把函数需要用到的值作为参数传入,完全不需要循环引用,也不需要依赖模块导出的状态,逻辑最清晰:
改后test1.js代码:
const { doStuff } = require("./test2.js"); let x = 1; setInterval(() => { console.log("Test1 :", x); x++; // 调用时直接把需要的x传进去 doStuff(x); }, 1000);
改后test2.js代码:
module.exports = { // 定义参数接收传入的值 doStuff(x){ console.log("Test2 :", x); }, };
这种方案不管你后续要传多少大体积对象都适用,只需要传个对象参数即可,完全不需要全局变量,也不会有缓存、循环引用之类的问题。
内容的提问来源于stack exchange,提问作者soulus
相关产品推荐
相关产品推荐

