В этом руководстве вы узнаете, как динамически импортировать модули с помощью функционального аналога import() в ES2020 JavaScript.
В ES6 представлена концепция модулей, позволяющая разрабатывать модульный код JavaScript. Предположим, у вас есть следующий простой HTML-документ с одной кнопкой:
<!DOCTYPE html> <html> <head> <title>Module Dynamic Import</title> </head> <body> <button id="show">Show Dialog</button> <script type="module" src="js/app.js"></script> </body> </html>
Когда пользователи нажимают кнопку, вы хотите показать диалоговое окно. Чтобы сделать код более организованным, вы разрабатываете модуль с именем dialog.js :
export function show(message) {
alert(message);
}И используете функцию show() в app.js :
import {show} from './dialog.js';
let btn = document.querySelector('#show');
btn.addEventListener('click', function () {
show('Hi');
});До ES2020 было невозможно динамически загружать модуль dialog.js при необходимости. Следующий пример вызовет ошибку:
let btn = document.querySelector('#show');
btn.addEventListener('click', function () {
import {show} from './dialog.js';
show('Hi');
});Приведенный выше код пытается загрузить модуль dialog.js только при нажатии кнопки.
ES2020 представил динамический импорт модуля с помощью функционального метода import() со следующим синтаксисом:
import(moduleSpecifier);
import() позволяет вам динамически импортировать модуль, когда это необходимо. Вот как работает функция:
import()принимает спецификатор модуля(moduleSpecifier), который имеет тот же формат, что и спецификатор модуля, используемый для оператораimport. Кроме того,moduleSpecifierможет быть выражением, результатом которого является строка.import()возвращаетPromise, которое будет выполнено после полной загрузки модуля.
Чтобы динамически загрузить dialog.js, вы можете использовать import() следующим образом:
let btn = document.querySelector('#show');
btn.addEventListener('click', function() {
import('./dialog.js')
.then(( dialog ) => {
dialog.show();
})
.catch( error => {
// handle error here
});
});Поскольку import() возвращает Promise, вы можете использовать async/await в модуле app.js следующим образом:
let btn = document.querySelector('#show');
btn.addEventListener('click', function () {
(async () => {
try {
let dialog = await import('./dialog.js');
dialog.show('Hi')
} catch (error) {
console.log(error);
}
})();
});Практические примеры
import() имеет следующие практические варианты использования:
1) Загрузка модуля по запросу
Некоторые функции могут быть недоступны при запуске приложений. Чтобы уменьшить время загрузки, вы можете разместить такие функции в модулях и использовать import() для их загрузки по запросу, например:
function eventHandler() {
import('./module1.js')
.then((ns) => {
// use the module
ns.func();
})
.catch((error) => {
// handle error
});
}2) Загрузка модулей в зависимости от условий
При размещении import() внутри условного оператора, такого как if-else, вы можете загружать модули на основе определенного условия. В следующем примере загружается модуль, ориентированный на определенную платформу:
if( isSpecificPlatform() ) {
import('./platform.js')
.then((ns) => {
ns=>f();
});
}3) Спецификаторы вычисляемого модуля
Спецификатор модуля — это выражение, которое позволяет вам решить, какой модуль загружать во время выполнения.
Например, вы можете загрузить модуль на основе локали пользователя, чтобы показать сообщение на конкретном языке пользователя:
let lang = `message_${getUserLocale()}.js`;
import(lang)
.then(...);Подробнее о функции
Использование деструктуризации объекта
Если модуль имеет несколько экспортов, вы можете использовать деструктуризацию объекта для получения экспортируемых объектов. Предположим, что dialog.js имеет две функции:
export function show(message) {
alert(message);
}
export function hide(message) {
console.log('Hide it...');
}В app.js вы можете использовать деструктуризацию объекта следующим образом:
let btn = document.querySelector('#show');
btn.addEventListener('click', function () {
(async () => {
try {
// use object destructuring
let {
show,
hide
} = await import('./dialog.js');
// use the functions
show('Hi');
hide();
} catch (err) {
console.log(err);
}
})();
});Динамическая загрузка нескольких модулей
Для динамической загрузки нескольких модулей вы можете использовать метод Promise.all() :
Promise.all([
import(module1),
import(module2),
...])
.then(([module1,module2,module3]) => {
// use the modules
});;Доступ к экспорту по умолчанию
Если у модуля есть экспорт по умолчанию, вы можете получить к нему доступ, используя ключевое слово default. Например:
import(moduleSpecifier)
.then((module) => {
// access the default export
console.log(module.default);
});Заключение
- Используйте JavaScript
import()для динамической загрузки модуля.import()возвращаетPromise, которое будет выполнено после полной загрузки модуля. - Используйте
async/awaitдля обработки результатаimport(). - Метод
Promise.all()— для одновременной загрузки нескольких модулей. - Чтобы назначить переменные экспортирующим объектам модуля, используйте деструктуризацию объекта.
- Ключевое слово
defaultобеспечивает доступ к экспорту по умолчанию.
