繁体   English   中英

理解 Node.js 模块:多个需要返回同一个对象?

[英]Understanding Node.js modules: multiple requires return the same object?

我有一个关于模块缓存的 node.js 文档的问题:

模块在第一次加载后被缓存。 这意味着(除其他外)每次调用 require('foo') 都会返回完全相同的对象,如果它解析为相同的文件。

多次调用 require('foo')可能不会导致模块代码被多次执行。 这是一个重要的特征。 有了它,可以返回“部分完成”的对象,从而允许加载传递依赖,即使它们会导致循环。

may是什么意思?

我想知道 require 是否总是返回相同的对象。 所以,如果我需要在一个模块A app.js和改变内部的出口对象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.jsb.js都驻留在同一个项目中(并且在同一个目录中),那么它们都会收到相同A实例 node.js 文档

... 每次调用require('foo')都会得到完全相同的对象返回,如果它解析为相同的文件


a.jsb.jsapp.js不同的 npm modules 中时,情况就不同了。 例如:

[APP] --> [A], [B]
[B]   --> [A]

在这种情况下, require('a')app.js将解析为一个不同的副本a.jsrequire('a')b.js ,因此返回的不同实例A 有一篇博客文章更详细地描述了这种行为。

node.js 实现了某种缓存,可以在执行一些大型服务器项目时阻止节点读取文件 1000 次。

此缓存在require.cache对象中列出。 我必须注意,这个对象是可读/可写的,它可以在不终止进程的情况下从缓存中删除文件。

http://nodejs.org/docs/latest/api/globals.html#require.cache

哦,忘记回答问题了。 修改导出的对象不会影响下一个模块加载。 这会造成很多麻烦... Require 总是返回一个新的对象实例,没有引用。 编辑文件并删除缓存确实会更改导出的对象

在做了一些测试之后,node.js 确实缓存了 module.exports。 修改require.cache[{module}].exports最终得到一个新的、修改过的返回对象。

自从发布问题以来,文档已更新,以明确最初使用“可能”的原因。 它现在通过使事情变得明确来回答问题本身(我强调的是显示发生了什么变化):

模块在第一次加载后被缓存。 这意味着(除其他外)每次调用 require('foo') 都会返回完全相同的对象,如果它解析为相同的文件。

提供require.cache没有被修改,多次调用要求(“富”)不会导致要多次执行该模块的代码。 这是一个重要的特征。 有了它,可以返回“部分完成”的对象,从而允许加载传递依赖,即使它们会导致循环。

就我所见,如果模块名称解析为先前加载的文件,则将返回缓存的模块,否则将单独加载新文件。

也就是说,缓存基于解析的实际文件名 这是因为,通常情况下,同一包的不同版本可能安装在文件层次结构的不同级别,并且必须相应地加载。

我不确定的是,是否存在不受程序员控制或意识的缓存失效情况,这可能会导致意外地多次重新加载相同的包文件。

如果您希望require(x)每次都返回一个新对象的原因仅仅是因为您直接修改了该对象 - 这是我遇到的一种情况 - 只需克隆它,然后只修改和使用克隆,如下所示:

var a = require('./a');
a = JSON.parse(JSON.stringify(a));

试试德雷克斯https : //github.com/yuryb/drex

drex 正在监视模块的更新,并在更新后干净地重新需要该模块。 新代码被 require() ,就好像新代码是一个完全不同的模块,所以 require.cache 不是问题。

当您需要一个对象时,您需要的是它的引用地址,而通过两次请求该对象,您将获得相同的地址! 要拥有相同对象的副本您应该复制(克隆)它。

var obj = require('./obj');

a = JSON.parse(JSON.stringify(obj));
b = JSON.parse(JSON.stringify(obj));
c = JSON.parse(JSON.stringify(obj));

克隆是通过多种方式完成的,你可以看到这个,了解更多信息。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM