Node.js删除require缓存后,导入的模块变量仍未更新是什么原因?
问题根因
问题的核心是CommonJS模块的导出机制和缓存刷新逻辑和你的预期不符,分为两个层面:
- 第一,CommonJS 对数字、字符串、布尔这类原始类型的导出是值拷贝,不是引用传递。你在 Mod1 中执行
module.exports = num时,num 当前值为6,导出的就是6这个固定的字面量值。后续 Mod1 内部修改 num 变量,只是修改了 Mod1 作用域内的变量,不会同步到已经导出的这个值上。 - 第二,删除 require 缓存重新加载模块的逻辑,本质是重新完整执行一遍 Mod1 的代码,每次执行都会创建一个全新的独立作用域:重新初始化
num=6、重新注册3秒后修改num的定时器。你每次重新导入拿到的都是新作用域下的初始值6,之前的定时器修改的是上一次加载产生的旧作用域里的变量,二者完全隔离,自然拿不到更新后的60。
正确实现方案
你不需要删除缓存,两种常用方案就能拿到运行时的最新值:
方案1:导出引用类型(推荐)
引用类型的导出是指针拷贝,指向同一个内存地址,修改内部属性所有引用处都能同步到最新值。
Mod1修改为:
var state = { num: 6 } function changeNum(){ state.num = 60 print(); } function print(){ console.log(state.num) } setTimeout(changeNum, 3000); module.exports = state
Mod2直接读取属性即可,不需要刷新导入:
const state = require('./mod1.js') async function logValue(){ console.log(state.num) await new Promise(resolve => setTimeout(resolve, 1000)); logValue(); } logValue();
方案2:导出取值函数
通过闭包拿到 Mod1 作用域内的最新变量值:
Mod1修改为:
var num = 6 function changeNum(){ num = 60 print(); } function print(){ console.log(num) } // 导出获取最新值的方法 exports.getNum = () => num setTimeout(changeNum, 3000);
Mod2调用方法取值:
const { getNum } = require('./mod1.js') async function logValue(){ console.log(getNum()) await new Promise(resolve => setTimeout(resolve, 1000)); logValue(); } logValue();
补充说明
删除 require 缓存的适用场景是你修改了模块的源文件代码,需要重新加载修改后的文件内容,和你当前运行时修改模块内部变量的场景完全不匹配,所以才会不生效。
内容的提问来源于stack exchange,提问作者Dave's a Beginner
相关产品推荐
相关产品推荐

