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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8887318/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 15:01:56  来源:igfitidea点击:

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

node.js

提问by Xomby

I have a question related to the node.js documentation on module caching:

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

Modules are cached after the first time they are loaded. This means (among other things) that every call to require('foo') will get exactly the same objectreturned, if it would resolve to the same file.

Multiple calls to require('foo') may not causethe module code to be executed multiple times. This is an important feature. With it, "partially done" objects can be returned, thus allowing transitive dependencies to be loaded even when they would cause cycles.

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

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

What is meant with may?

是什么意思may

I want to know if require will alwaysreturn the same object. So in case I require a module Ain app.jsand change the exports object within app.js(the one that require returns) and after that require a module Bin app.jsthat itself requires module A, will I alwaysget the modified version of that object, or a new one?

我想知道 require 是否总是返回相同的对象。所以,如果我需要一个模块一个app.js和改变内部的出口对象app.js(需要回报的),之后需要一个模块app.js本身需要模块一个,我将永远得到该对象的修改版本或新一?

// 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');

回答by Petr Stodulka

If both app.jsand b.jsreside in the same project(and in the same directory) then both of them will receive the same instanceof A. From the node.js documentation:

如果app.jsb.js都驻留在同一个项目中(并且在同一个目录中),那么它们都会收到相同A. 从node.js 文档

... every call to require('foo')will get exactly the same objectreturned, if it would resolve to the same file.

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



The situation is different when a.js, b.jsand app.jsare in different npm modules. For example:

这种情况是不同的,当a.jsb.js并且app.js不同的NPM模块。例如:

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

In that case the require('a')in app.jswould resolve to a different copy of a.jsthan require('a')in b.jsand therefore return a different instanceof A. There is a blog postdescribing this behavior in more detail.

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

回答by moe

node.js has some kind of caching implemented which blocks node from reading files 1000s of times while executing some huge server-projects.

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

This cache is listed in the require.cacheobject. I have to note that this object is read/writeable which gives the ability to delete files from the cache without killing the process.

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

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

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

Ouh, forgot to answer the question. Modifying the exported object does not affect the next module-loading. This would cause much trouble... Require always return a new instance of the object, no reference.Editing the file and deleting the cache does change the exported object

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

After doing some tests, node.js does cache the module.exports. Modifying require.cache[{module}].exportsends up in a new, modified returned object.

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

回答by Reg Edit

Since the question was posted, the documenthas been updated to make it clear why "may" was originally used. It now answers the question itself by making things explicit (my emphasis to show what's changed):

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

Modules are cached after the first time they are loaded. This means (among other things) that every call to require('foo') will get exactly the same object returned, if it would resolve to the same file.

Provided require.cache is not modified,multiple calls to require('foo') willnot cause the module code to be executed multiple times. This is an important feature. With it, "partially done" objects can be returned, thus allowing transitive dependencies to be loaded even when they would cause cycles.

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

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

回答by Simone C.

For what I have seen, if the module name resolve to a file previosuly loaded, the cached module will be returned, otherwise the new file will be loaded separately.

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

That is, caching is based on the actual file namethat gets resolved. This is because, in general, there can be different versions of the same package that are installed at different levels of the file hierarchy and that must be loaded accordingly.

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

What I am not sure about is wether there are cases of cache invalidation not under the programmer's control or awareness, that might make it possible to accidentaly reload the very same package file multiple times.

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

回答by Eugene Beresovsky

In case the reason why you want require(x)to return a fresh object every time is just because you modify that object directly - which is a case I ran into - just clone it, and modify and use only the clone, like this:

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

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

回答by user2030657

try drex: https://github.com/yuryb/drex

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

drex is watching a module for updates and cleanly re-requires the module after the update. New code is being require()d as if the new code is a totally different module, so require.cache is not a problem.

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

回答by Amir Fo

When you require an object, you are requiring its reference address, and by requiring the object twice, you will get the same address! To have copies of the same object, You should copy (clone) it.

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

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

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

Cloning is done in multiple ways, you can see this, for further information.

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