#javascript #typescript #es6-modules #circular-dependency
#javascript #typescript #es6-модули #циклическая зависимость
Вопрос:
Я попробовал madge
приложение TypeScript, над которым я работаю:
npx madge --circular --extensions ts src/
И получил длинный дамп циклических зависимостей (на самом деле их 61). Однако дело в том, что приложение компилируется и работает нормально. Как это возможно? Существуют ли определенные условия, при которых циклические зависимости превращаются в проблему?
Ответ №1:
Синхронный циклический импорт, как правило, в порядке. Думайте о них как о объявлениях, они на самом деле ничего не выполняют. До тех пор, пока вы не используете импорт немедленно, синхронно. Например, это работает:
A.js:
import B from 'B.js'
export function A() {
if (/* some condition that doesn't last forever */) return B()
else return 0 // of course, you don't want an infinite recursive loop either ;)
}
B.js:
import A from 'A.js'
export function B() {
if (/* some condition that doesn't last forever */) return A()
else return 0 // same thing
}
Вы можете импортировать A и B в другой файл и вызвать их оба там, все будет в порядке. A и B ссылаются друг на друга, но им не нужно использовать друг друга, пока не будет вызван один из них.
Но если вы используете один из двух экспортов синхронно, в то время как другой еще не экспортирован, это приведет к сбою:
A.js:
import B from 'B.js'
export const A = B(something)
B.js:
import A from 'A.js'
export function B() {
return A
}
Теперь здесь происходит то, что оценка A (которая должна быть выполнена перед ее экспортом) требует вызова B , а для запуска B требуется, чтобы A уже был определен.
Комментарии:
1. Есть ли способ (в
madge
или любой другой инструмент) выгружать только синхронные циклические зависимости?2. Я не знаю. Циклический динамический импорт определенно вызовет ошибку, поэтому вам действительно следует беспокоиться о них, а не о синхронном импорте (последние часто объединяются в один файл в любом случае во время процесса сборки).
3. Я просто избегаю циклических зависимостей во всей их полноте в typescript, используя основной индекс экспорта. Экспортируйте ВСЕ через один корневой индекс и импортируйте ВСЕ из этого корневого индекса. Нулевой относительный или индивидуальный импорт файлов. Вы можете экспортировать папки через дочерние индексы и т. Д. И экспортировать их из основного индекса. Но это дает вам один симпатичный график в madge. Затем полагайтесь на тряску webpack или дерева свертки, чтобы отбросить вещи, которые вы не используете. Если у вас есть конфликтующие имена, просто используйте пространство имен для экспорта, например ‘export * as things from ‘./someIndex»
4. Я не понимаю, как это позволяет избежать циклических зависимостей. Вы просто делаете их косвенными. Вместо «A требует B из B.js» и «B требует A из A.js» у вас будет «A требует B из индекса» и «B требует A из индекса», при этом индекс повторно экспортирует как A, так и B из их соответствующих файлов (возможно, путем перебора дополнительных индексов).