我有一个与 the node.js documentation on module caching 相关的问题:
模块在第一次加载后被缓存。这意味着(除其他外)每次调用 require('foo') 都将返回完全相同的对象,如果它会解析为同一个文件。多次调用 require('foo') 可能不会导致模块代码被多次执行。这是一个重要的特点。有了它,可以返回“部分完成”的对象,从而允许加载传递依赖项,即使它们会导致循环。
may
是什么意思?
我想知道 require 是否会总是返回相同的对象。因此,如果我在 app.js
中需要一个模块 A 并更改 app.js
中的导出对象(需要返回的对象),然后需要一个模块 B 在app.js
本身需要模块 A,我会总是获得该对象的修改版本还是新版本?
// app.js
var a = require('./a');
a.b = 2;
console.log(a.b); //2
var b = require('./b');
console.log(b.b); //2
// a.js
exports.a = 1;
// b.js
module.exports = require('./a');
如果 app.js
和 b.js
都驻留在 同一个项目中(并且在同一个目录中),那么它们都将收到 A
的同一个实例。从 node.js documentation:
...每次调用 require('foo') 都将返回完全相同的对象,如果它会解析为同一个文件。
当 a.js
、b.js
和 app.js
位于不同的 npm 模块中时,情况会有所不同。例如:
[APP] --> [A], [B]
[B] --> [A]
在这种情况下,app.js
中的 require('a')
将解析为与 b.js
中的 require('a')
不同的 a.js
副本,因此返回 A
的不同实例。有一个 blog post 更详细地描述了这种行为。
node.js 实现了某种缓存,在执行一些大型服务器项目时阻止 node 读取文件 1000 次。
此缓存列在 require.cache
对象中。我必须注意,这个对象是可读/可写的,它可以从缓存中删除文件而不会终止进程。
http://nodejs.org/docs/latest/api/globals.html#require.cache
哦,忘记回答问题了。修改导出的对象不会影响下一次模块加载。这会造成很多麻烦......要求总是返回一个新的对象实例,没有引用。编辑文件并删除缓存确实会更改导出的对象
在做了一些测试之后,node.js 确实缓存了 module.exports。修改 require.cache[{module}].exports
以一个新的、修改后的返回对象结束。
b.b
用值 2
定义。所以在这个例子中它是同一个对象。
may
这使得它不清楚。
自问题发布以来,已更新 the document 以明确说明最初使用“可能”的原因。它现在通过使事情变得明确来回答问题本身(我强调显示发生了什么变化):
模块在第一次加载后被缓存。这意味着(除其他外)每次调用 require('foo') 都将返回完全相同的对象,如果它会解析为同一个文件。如果 require.cache 没有被修改,多次调用 require('foo') 不会导致模块代码被多次执行。这是一个重要的特点。有了它,可以返回“部分完成”的对象,从而允许加载传递依赖项,即使它们会导致循环。
对于我所看到的,如果模块名称解析为先前加载的文件,则将返回缓存的模块,否则将单独加载新文件。
也就是说,缓存基于得到解析的实际文件名。这是因为,一般来说,同一包的不同版本可能安装在文件层次结构的不同级别,并且必须相应地加载。
我不确定是否存在不受程序员控制或意识的缓存失效的情况,这可能会导致意外地多次重新加载相同的包文件。
如果您希望 require(x)
每次都返回一个新对象的原因仅仅是因为您直接修改了该对象 - 这是我遇到的一种情况 - 只需克隆它,然后修改并只使用克隆,如下所示:
var a = require('./a');
a = JSON.parse(JSON.stringify(a));
试试 drex:https://github.com/yuryb/drex
drex 正在监视一个模块的更新,并在更新后干净地重新需要该模块。新代码被 require()d 就好像新代码是一个完全不同的模块,所以 require.cache 不是问题。
当你需要一个对象时,你需要它的引用地址,并且通过两次需要该对象,你将获得相同的地址!要拥有相同对象的副本,您应该复制(克隆)它。
var obj = require('./obj');
a = JSON.parse(JSON.stringify(obj));
b = JSON.parse(JSON.stringify(obj));
c = JSON.parse(JSON.stringify(obj));
克隆以多种方式完成,您可以查看 this,了解更多信息。
不定期副业成功案例分享