Node.js - модуль кеширования, частично выполненные объекты и циклические зависимости? - PullRequest
6 голосов
/ 09 июня 2011

В документации node.js, касающейся кеширования модуля , сделано следующее утверждение:

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

Я немного запутался в последнемпредложение.Что такое «частично выполненный» объект?Как это относится к разрешению (или предотвращению) циклических зависимостей?

Ответы [ 2 ]

5 голосов
/ 10 июня 2011

Если вы require пакет из файла, и это вызывает файл в этом пакете для require файл, который вызвал начальный require, то у вас есть циклическая зависимость. По умолчанию это будет просто идти по кругу. Чтобы предотвратить это, можно сохранить маркер, с которого начался require, чтобы в следующий раз этот файл был require, и он начнется с этой точки, а не с начала. Он не безупречен, но в случае загрузки пакета вас интересует только экспорт, и в этом случае он работает хорошо.

Я выдвинул diff для node-browserify некоторое время назад для примитивного метода «частично выполненного» экспорта. По сути, каждый раз, когда что-то require будет проверять объем экспорта. Если есть больше экспорта, это означает, что пакет был неполным в прошлый раз, и все еще мог обрабатываться. Если нет новых экспортов (новые и старые счетчики равны), то это означает, что пакет завершен, и его можно кэшировать, чтобы код модуля не выполнялся несколько раз. Поскольку он находится в браузере, нет никакого контроля над потоком выполнения, и, таким образом, код модуля будет повторяться частично (по шагам), пока не будет выполнено. Я уверен, что Node.js обладает более элегантной обработкой.

1 голос
/ 04 января 2017

В документации node.js приведен хороший и понятный пример . Он проливает больше света на "частично выполненный" объект и циклические зависимости.

Когда есть циклические вызовы require (), модуль может не завершиться, когда возвращается.

Рассмотрим эту ситуацию:

a.js:

console.log('a starting');
exports.done = false;
const b = require('./b.js');
console.log('in a, b.done = %j', b.done);
exports.done = true;
console.log('a done');

b.js:

console.log('b starting');
exports.done = false;
const a = require('./a.js');
console.log('in b, a.done = %j', a.done);
exports.done = true;
console.log('b done');

main.js:

console.log('main starting');
const a = require('./a.js');
const b = require('./b.js');
console.log('in main, a.done=%j, b.done=%j', a.done, b.done);

Когда main.js загружает a.js, тогда a.js, в свою очередь, загружает b.js. В этот момент b.js пытается загрузить a.js. Чтобы предотвратить бесконечный цикл, незаконченная копия объекта экспорта a.js возвращается в модуль b.js. Затем b.js заканчивает загрузку, и его объект экспорта передается в модуль a.js.

К тому времени, когда main.js загрузил оба модуля, они оба закончили. Результат этой программы будет таким:

узел main.js

main starting
a starting
b starting
in b, a.done = false
b done
in a, b.done = true
a done
in main, a.done=true, b.done=true
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...