Понимание модулей Node.js: несколько требует возврата одного и того же объекта? - PullRequest
93 голосов
/ 17 января 2012

У меня есть вопрос, связанный с документацией node.js по кешированию модулей :

Модули кэшируются после первой загрузки.Это означает (среди прочего), что каждый вызов require ('foo') будет получать точно такой же возвращенный объект , если он будет преобразован в один и тот же файл.

Требуется несколько вызовов('foo') не может привести к многократному выполнению кода модуля.Это важная особенность.С его помощью могут быть возвращены «частично выполненные» объекты, что позволяет загружать транзитивные зависимости, даже если они вызывают циклы.

Что подразумевается под may?

Iхотите знать, если требуется, будет всегда возвращать один и тот же объект.Таким образом, в случае, если мне требуется модуль 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');

Ответы [ 6 ]

64 голосов
/ 02 ноября 2014

Если оба app.js и b.js находятся в в одном проекте (и в одном каталоге), то оба они получат один и тот же экземпляр из A.Из документации node.js :

... каждый вызов require('foo') будет возвращать точно такой же объект , если он будет разрешен к тому же файлу .


Ситуация отличается, когда a.js, b.js и app.js находятся в различных модулях npm .Например:

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

В этом случае require('a') в app.js разрешит другую копию a.js, чем require('a') в b.js и, следовательно, вернет другой экземпляр из A.В блоге 1039 * более подробно описывается это поведение.

5 голосов
/ 17 января 2012

В файле node.js реализовано какое-то кэширование, которое блокирует чтение узлов файлами 1000 раз при выполнении некоторых огромных серверных проектов.

Этот кэш находится в объекте require.cache.Я должен отметить, что этот объект доступен для чтения / записи, что дает возможность удалять файлы из кэша, не убивая процесс.

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

Ой, забыл ответить на вопрос. Изменение экспортируемого объекта не влияет на следующую загрузку модуля.Это может вызвать много проблем ... Требовать всегда возвращать новый экземпляр объекта, без ссылки. Редактирование файла и удаление кэша изменяет экспортируемый объект

После выполнения некоторых тестов, node.jsкеширует module.exports.Изменение require.cache[{module}].exports заканчивается новым, измененным возвращенным объектом.

2 голосов
/ 27 октября 2013

Для того, что я видел, если имя модуля преобразуется в файл, ранее загруженный, кэшированный модуль будет возвращен, в противном случае новый файл будет загружен отдельно.

То есть кэширование основано на действительном имени файла , которое разрешается. Это связано с тем, что в общем случае разные версии одного и того же пакета могут быть установлены на разных уровнях файловой иерархии и должны быть соответственно загружены.

В чем я не уверен, так это в тех случаях, когда существуют случаи недействительности кэша, не находящиеся под контролем или осознанием программиста, которые могут позволить случайно перезагрузить один и тот же файл пакета несколько раз.

1 голос
/ 16 октября 2018

Поскольку вопрос был опубликован, документ был обновлен, чтобы было понятно, почему слово "возможно" было изначально использовано. Теперь он отвечает на сам вопрос, делая вещи явными (мой акцент, чтобы показать, что изменилось):

Модули кэшируются после первой загрузки. Это означает (среди прочего), что каждый вызов require ('foo') получит точно такой же объект возвращается, если он будет разрешен к тому же файл.

При условии, что require.cache не изменяется, несколько вызовов на require ('foo') не будет не вызывать многократное выполнение кода модуля раз. Это важная особенность. При этом «частично выполненные» объекты могут быть возвращены, что позволяет загружать транзитивные зависимости даже когда они вызывают циклы.

0 голосов
/ 12 января 2018

В случае, если вы хотите, чтобы require(x) возвращал свежий объект каждый раз, просто потому, что вы изменяете этот объект напрямую - в этом случае я столкнулся - просто клонируйте его, изменяйте и используйте только клон, напримерэто:

var a = require('./a');
a = JSON.parse(JSON.stringify(a));
0 голосов
/ 01 февраля 2013

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

drex просматривает модуль для обновлений и заново требует модуль после обновления. Новый код требует (), как будто новый Код - это совершенно другой модуль, поэтому require.cache не проблема.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...