ES6: Умови умовного та динамічного імпорту


85

Умовні

Чи можна мати умови умовного імпорту, як показано нижче?

if (foo === bar) {
    import Baz from './Baz';
}

Я спробував вищезазначене, але при компіляції отримую таку помилку (від Babel).

'import' and 'export' may only appear at the top level

Динамічний

Чи можна мати динамічні оператори імпорту, як показано нижче?

for (let foo in bar) {
    if (bar.hasOwnProperty(foo)) {
        import Baz from `./${foo}`;
    }
}

Вище зазначене отримує ту ж помилку від Babel під час компіляції.

Чи можливо це зробити, чи щось мені не вистачає?

Міркування

Причина, за якою я намагаюся це зробити, полягає в тому, що у мене багато імпорту для ряду "сторінок", і вони дотримуються подібної схеми. Я хотів би очистити свою базу коду, імпортуючи ці файли з динамічним циклом for.

Якщо це неможливо, то чи є кращий спосіб обробляти велику кількість імпорту в ES6?


1
не може бути використана спадщина в такому випадку? використовувати superдля виклику конкретних.
Джай

Я вже використовую успадкування, але ці "сторінки" містять специфічну логіку "сторінки". У мене є базовий клас "сторінка", який усі розширюється, але цього недостатньо, щоб очистити величезну кількість імпорту, який я маю.
Enijar

1
@zerkms: Вони не виведені з блоків - це синтаксичні помилки.
Бергі

можливий дублікат імені імпорту змінної ES6 у node.js ?
Бергі

Відповіді:


54

Зараз ми маємо пропозицію щодо динамічного імпорту з ECMA. Це на етапі 2. Це також доступно як попередньо встановлене значення .

Нижче наведено спосіб зробити умовний візуалізацію відповідно до вашого випадку.

if (foo === bar) {
    import('./Baz')
    .then((Baz) => {
       console.log(Baz.Baz);
    });
}

Це в основному повертає обіцянку. Очікується, що модуль дозволить обіцянку. У пропозиції також є такі речі, як багаторазовий динамічний імпорт, імпорт за замовчуванням, імпорт файлів js тощо. Більше інформації про динамічний імпорт можна знайти тут .


3
Це. Динамічний імпорт - це шлях. Вони працюють так само, як require (), за винятком того, що дають вам обіцянку, а не модуль.
надсвітлий

24

Ви не можете динамічно вирішити свої залежності, як importsце призначено для статичного аналізу. Тим не менш, ви можете скористатися деякими requireтут, приблизно такими:

for (let foo in bar) {
    if (bar.hasOwnProperty(foo)) {
        const Baz = require(foo).Baz;
    }
}

8
"оскільки імпорт призначений для статичного аналізу." --- це твердження невизначене. imports призначені для імпорту, а не для аналізу.
zerkms

12
@zerkms - Я думаю, що вони мали на увазі те, що importвисловлювання мають бути придатними для статичного аналізу - оскільки вони ніколи не є умовними, інструменти можуть простіше аналізувати дерева залежностей.
Джо Клей

4
Важко зрозуміти за допомогою "foo", "baz" та "bar" - як щодо прикладу з реального життя?
TetraDev

1
Це вже неправда. Зараз динамічний імпорт - це річ. Дивіться тут: stackoverflow.com/a/46543949/687677
надсвітний

7

Оскільки це питання високо оцінене Google, варто зазначити, що з часом розміщення старих відповідей все змінилося.

MDN має цей запис у розділі Динамічний імпорт :

Ключове слово import може бути викликано як функція для динамічного імпорту модуля. При такому використанні він повертає обіцянку.

import('/modules/my-module.js')
  .then((module) => {
    // Do something with the module.
  });

// This form also supports the await keyword.
let module = await import('/modules/my-module.js');

Корисну статтю на цю тему можна знайти на сайті Medium .


1

Require не вирішить вашу проблему, оскільки це синхронний дзвінок. Є кілька варіантів, і всі вони включають

  1. Запитуючи модуль, який вам потрібен
  2. Чекаючи обіцянки повернення модуля

У ECMA Script передбачена підтримка модулів лінивого завантаження за допомогою SystemJS. Звичайно, це підтримується не у всіх браузерах, тому тим часом ви можете використовувати JSPM або шину SystemJS.

https://github.com/ModuleLoader/es6-module-loader


1

З 2016 року у світі JavaScript пройшло багато, тому я вважаю, що настав час запропонувати найсвіжішу інформацію на цю тему. В даний час динамічне імпортування є реальністю як на Node, так і в браузерах (спочатку, якщо ви не дбаєте про IE, або за допомогою @ babel / plugin-syntax-dynamic-import, якщо вам все одно).

Отже, розглянемо зразок модуля something.jsз двома названими експортами та одним експортом за замовчуванням:

export const hi = (name) => console.log(`Hi, ${name}!`)
export const bye = (name) => console.log(`Bye, ${name}!`)
export default () => console.log('Hello World!')

Ми можемо використовувати import()синтаксис, щоб легко та чисто завантажити його умовно:

if (somethingIsTrue) {
  import('./something.js').then((module) => {
    // Use the module the way you want, as:
    module.hi('Erick') // Named export
    module.bye('Erick') // Named export
    module.default() // Default export
  })
}

Але так як повернення є Promise, то async/ awaitсинтаксичний цукор також можливо:

async imAsyncFunction () {
  if (somethingIsTrue) {
    const module = await import('./something.js')
    module.hi('Erick')
  }
}

А тепер подумайте про можливості разом із Призначенням деструктуризації об’єктів ! Наприклад, ми можемо легко помістити лише один із названих експортів в пам’ять для використання ззаду:

const { bye } = await import('./something.js')
bye('Erick')

Або, можливо, захопіть один із названих експортів та перейменуйте його на будь-що інше, що ми хочемо:

const { hi: hello } = await import('./something.js')
hello('Erick')

Або навіть перейменувати експортовану за замовчуванням функцію на щось, що має більше сенсу:

const { default: helloWorld } = await import('./something.js')
helloWorld()

Лише остання (але не менш важлива) примітка: import() може виглядати як виклик функції, але це не є Function. Це спеціальний синтаксис, який просто використовує дужки (подібно до того, що відбувається з super()). Тому неможливо призначити importзмінну або використовувати речі Functionпрототипу, наприклад call/ apply.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.