You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 08:42:01