在node.js文档中:
模块在第一次加载后被缓存。这意味着(除其他外)每次调用require('foo')都会得到完全相同的返回对象,如果它将解析到相同的文件。
是否有一种方法使这个缓存无效?例如,对于单元测试,我希望每个测试都在一个新鲜的对象上工作。
在node.js文档中:
模块在第一次加载后被缓存。这意味着(除其他外)每次调用require('foo')都会得到完全相同的返回对象,如果它将解析到相同的文件。
是否有一种方法使这个缓存无效?例如,对于单元测试,我希望每个测试都在一个新鲜的对象上工作。
当前回答
解决方法是:
delete require.cache[require.resolve(<path of your script>)]
对于那些像我一样在这方面有点新手的人,这里有一些基本的解释:
假设你在根目录下有一个虚拟example.js文件:
exports.message = "hi";
exports.say = function () {
console.log(message);
}
然后像这样要求():
$ node
> require('./example.js')
{ message: 'hi', say: [Function] }
如果你在example.js中添加如下一行:
exports.message = "hi";
exports.say = function () {
console.log(message);
}
exports.farewell = "bye!"; // this line is added later on
并在控制台中继续,该模块没有更新:
> require('./example.js')
{ message: 'hi', say: [Function] }
这时你可以使用delete require.cache[require.resolve()]在luff的回答中指出:
> delete require.cache[require.resolve('./example.js')]
true
> require('./example.js')
{ message: 'hi', say: [Function], farewell: 'bye!' }
因此缓存被清理,require()再次捕获文件的内容,加载所有当前值。
其他回答
如果是用于单元测试,另一个可以使用的好工具是proxyquire。每次你代理模块时,它都会使模块缓存失效,并缓存一个新的模块。它还允许您修改正在测试的文件所需的模块。
解决方法是:
delete require.cache[require.resolve(<path of your script>)]
对于那些像我一样在这方面有点新手的人,这里有一些基本的解释:
假设你在根目录下有一个虚拟example.js文件:
exports.message = "hi";
exports.say = function () {
console.log(message);
}
然后像这样要求():
$ node
> require('./example.js')
{ message: 'hi', say: [Function] }
如果你在example.js中添加如下一行:
exports.message = "hi";
exports.say = function () {
console.log(message);
}
exports.farewell = "bye!"; // this line is added later on
并在控制台中继续,该模块没有更新:
> require('./example.js')
{ message: 'hi', say: [Function] }
这时你可以使用delete require.cache[require.resolve()]在luff的回答中指出:
> delete require.cache[require.resolve('./example.js')]
true
> require('./example.js')
{ message: 'hi', say: [Function], farewell: 'bye!' }
因此缓存被清理,require()再次捕获文件的内容,加载所有当前值。
以下两步程序对我来说非常有效。
在动态更改模型文件i-e 'mymodule.js'后,你需要先删除预编译的模型,然后使用require-reload重新加载它
Example:
// Delete mongoose model
delete mongoose.connection.models[thisObject.singular('mymodule')]
// Reload model
var reload = require('require-reload')(require);
var entityModel = reload('./mymodule.js');
是的,您可以通过require访问缓存。缓存[moduleName],其中moduleName是你想要访问的模块名。通过调用delete require删除一个条目。cache[moduleName]将导致require加载实际文件。
这是删除与模块相关的所有缓存文件的方法:
/**
* Removes a module from the cache
*/
function purgeCache(moduleName) {
// Traverse the cache looking for the files
// loaded by the specified module name
searchCache(moduleName, function (mod) {
delete require.cache[mod.id];
});
// Remove cached paths to the module.
// Thanks to @bentael for pointing this out.
Object.keys(module.constructor._pathCache).forEach(function(cacheKey) {
if (cacheKey.indexOf(moduleName)>0) {
delete module.constructor._pathCache[cacheKey];
}
});
};
/**
* Traverses the cache to search for all the cached
* files of the specified module name
*/
function searchCache(moduleName, callback) {
// Resolve the module identified by the specified name
var mod = require.resolve(moduleName);
// Check if the module has been resolved and found within
// the cache
if (mod && ((mod = require.cache[mod]) !== undefined)) {
// Recursively go over the results
(function traverse(mod) {
// Go over each of the module's children and
// traverse them
mod.children.forEach(function (child) {
traverse(child);
});
// Call the specified callback providing the
// found cached module
callback(mod);
}(mod));
}
};
用法如下:
// Load the package
var mypackage = require('./mypackage');
// Purge the package from cache
purgeCache('./mypackage');
因为这段代码使用了相同的解析器require does,所以只需要为require指定所需的内容。
Unix的设计初衷并不是为了阻止用户做愚蠢的事情 这也会阻止他们做一些聪明的事情。”——道格·格温
我认为应该有一种方法来执行显式的非缓存模块加载。
我将在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)
}