在node.js文档中:
模块在第一次加载后被缓存。这意味着(除其他外)每次调用require('foo')都会得到完全相同的返回对象,如果它将解析到相同的文件。
是否有一种方法使这个缓存无效?例如,对于单元测试,我希望每个测试都在一个新鲜的对象上工作。
在node.js文档中:
模块在第一次加载后被缓存。这意味着(除其他外)每次调用require('foo')都会得到完全相同的返回对象,如果它将解析到相同的文件。
是否有一种方法使这个缓存无效?例如,对于单元测试,我希望每个测试都在一个新鲜的对象上工作。
当前回答
我将在luff的答案中再添加一行并更改参数名称:
function requireCached(_module){
var l = module.children.length;
for (var i = 0; i < l; i++)
{
if (module.children[i].id === require.resolve(_module))
{
module.children.splice(i, 1);
break;
}
}
delete require.cache[require.resolve(_module)];
return require(_module)
}
其他回答
您总是可以安全地删除require中的条目。缓存没有问题,即使有循环依赖。因为当你删除时,你只是删除了缓存的模块对象的引用,而不是模块对象本身,模块对象不会被GCed,因为在循环依赖的情况下,仍然有一个对象引用这个模块对象。
假设你有:
脚本a.js:
var b=require('./b.js').b;
exports.a='a from a.js';
exports.b=b;
和脚本b.js:
var a=require('./a.js').a;
exports.b='b from b.js';
exports.a=a;
当你这样做时:
var a=require('./a.js')
var b=require('./b.js')
你会得到:
> a
{ a: 'a from a.js', b: 'b from b.js' }
> b
{ b: 'b from b.js', a: undefined }
现在如果你编辑你的b.js:
var a=require('./a.js').a;
exports.b='b from b.js. changed value';
exports.a=a;
和做的事:
delete require.cache[require.resolve('./b.js')]
b=require('./b.js')
你会得到:
> a
{ a: 'a from a.js', b: 'b from b.js' }
> b
{ b: 'b from b.js. changed value',
a: 'a from a.js' }
===
如果直接运行node.js,上述语句有效。然而,如果使用的工具有自己的模块缓存系统,比如jest,正确的语句应该是:
jest.resetModules();
我将在luff的答案中再添加一行并更改参数名称:
function requireCached(_module){
var l = module.children.length;
for (var i = 0; i < l; i++)
{
if (module.children[i].id === require.resolve(_module))
{
module.children.splice(i, 1);
break;
}
}
delete require.cache[require.resolve(_module)];
return require(_module)
}
文件说:
当需要模块时,模块缓存在这个对象中。通过从该对象中删除键值,下一个require将重新加载该模块。这不适用于本机插件,因为重新加载将导致错误。
对于任何使用Jest的人来说,因为Jest有自己的模块缓存,所以有一个内置的函数-只要确保Jest。resetModules运行eg。每次测试后:
afterEach( function() {
jest.resetModules();
});
在尝试使用decache后发现了这一点,就像另一个答案建议的那样。感谢安东尼·加文。
函数文档在这里。
对于这个用例,重新连接非常有用,每次调用都会得到一个新实例。简单的依赖注入node.js单元测试。
Rewire为模块添加了一个特殊的setter和getter,这样您就可以修改它们的行为以进行更好的单元测试。你可能
为其他模块或全局变量(如process)注入mock 泄露私有变量 重写模块内的变量。 Rewire不会加载文件并计算内容以模拟节点的require机制。实际上,它使用节点自己的require来加载模块。因此,您的模块在测试环境中的行为与常规情况下完全相同(除了您的修改)。
对所有咖啡因成瘾者来说,这是个好消息:重新连接也适用于Coffee-Script。注意,在这种情况下CoffeeScript需要被列在你的devDependencies中。