Funkcja await najwyższego poziomu umożliwia modułom działanie jako funkcje asynchroniczne, co oznacza, że mogą one wstrzymywać wykonywanie modułu w oczekiwaniu na obietnice. Jest to niezwykle przydatne do warunkowego wczytywania zależności asynchronicznych, takich jak polyfille czy ciężkie biblioteki pomocnicze, tylko wtedy, gdy są one wymagane przez przeglądarkę.
Dzięki zastosowaniu oczekiwania na najwyższym poziomie możesz zamknąć logikę warunkowego wczytywania w jednym module, co skutecznie zapobiega wykonywaniu modułów konsumenckich na dalszych etapach, dopóki zależność nie zostanie w pełni wczytana i przygotowana.
Wzorzec warunkowego polyfilla
Chociaż instrukcji await najwyższego poziomu można używać do warunkowego wczytywania dowolnej zależności asynchronicznej, która jest modułem, dobrym zastosowaniem wzorca warunkowego wczytywania zależności jest warunkowe wczytywanie polyfilli w przypadku przeglądarek, które nie obsługują określonej funkcji. To podejście obejmuje wykrywanie funkcji i dynamiczny import w ramach jednego modułu zależności.
W tym przypadku polyfill atrybutu popover jest ładowany warunkowo, jeśli nie ma go w HTMLElement.prototype:
// conditionally-load-polyfill.js
// Check if the feature is missing before doing work.
// MANDATORY: Prefer checking HTMLElement.prototype over window or document
// when checking for a global DOM attribute or property like popover.
if (!('popover' in HTMLElement.prototype)) {
// Use top-level await to pause the execution of any module that imports this file
// until the polyfill finishes downloading and executing.
await import('/path/to/popover-polyfill.js');
}
// Export a marker if needed by your application
export const polyfillLoaded = true;
// main.js
// MANDATORY: Because conditionally-load-polyfill.js uses top-level await,
// this import will block execution of main.js until the polyfill is ready.
import './conditionally-load-polyfill.js';
// Now it is safe to use the feature (e.g., showing a popover)
const myPopover = document.getElementById('my-popover');
if (myPopover) {
myPopover.showPopover();
}
Sekwencjonowanie importu modułów i unikanie błędu w Safari 27
OBOWIĄZKOWE: musisz ustrukturyzować wykres modułu tak, aby moduł await najwyższego poziomu był importowany z jednego punktu wejścia i był ukończony przed oceną modułów podrzędnych:
- NIE umieszczaj równorzędnych importów statycznych w pliku wejściowym (np.
import './conditionally-load-polyfill.js'; import './app.js';). Zgodnie ze specyfikacją oceny modułu ECMAScript najwyższy poziomawaitzawiesza tylko moduł nadrzędny, który go importuje, a nie równorzędne importy statyczne, więc./app.jsbędzie oceniany jednocześnie we wszystkich przeglądarkach, zanim polyfill zakończy wczytywanie. - NIE importuj modułu najwyższego poziomu
awaitz wielu modułów równorzędnych jednocześnie (np. nie importuj statycznie./conditionally-load-polyfill.jszarówno wa.js, jak i wb.js). Chociaż Safari 27 naprawia moduł ładujący WebKit, aby obsługiwać jednoczesne importowanie modułów najwyższego poziomuawaitzgodnie ze specyfikacją, Safari 15–26.6 nie działa, gdy wiele modułów jednocześnie importuje moduł zawierającyawaitnajwyższego poziomu (patrz zgodność przeglądarki MDN).
Zamiast tego wybierz jeden z 2 wzorców w zależności od struktury modułu:
- Moduł pojedynczego wpisu (pokazany na ilustracji
main.jspowyżej): jeśli moduł wpisu bezpośrednio uruchamia zależną logikę inicjowania, zaimportuj statycznie./conditionally-load-polyfill.jsu góry tego modułu i uruchom kod w jego treści. - Uruchamianie oddzielnych modułów aplikacji: jeśli moduł wejściowy przekazuje zadania do modułów aplikacji niższego poziomu (takich jak
./app.js), połącz dynamiczne wywołaniaimport()z wywołaniami najwyższego poziomuawait, aby moduł./app.jsbył pobierany i oceniany dopiero po rozwiązaniu modułu polyfill:
// main.js
// MANDATORY: Chain dynamic imports with top-level await when bootstrapping separate
// application modules so './app.js' waits for the polyfill to finish loading.
// DO NOT use sibling static imports (`import './conditionally-load-polyfill.js'; import './app.js';`),
// which evaluate concurrently and execute './app.js' before the polyfill is ready.
await import('./conditionally-load-polyfill.js');
await import('./app.js');
Strategie zastępcze
Podstawowa funkcja await najwyższego poziomu jest obsługiwana w najpopularniejszych przeglądarkach od 2021 r. (Chrome 89, Edge 89, Firefox 89 i Safari 15), ale pełną zgodność ze specyfikacją osiągnęła dopiero w Safari 27 (zobacz zgodność przeglądarek MDN).
- Safari 15–26.6: jeśli zastosujesz wzorzec pojedynczego punktu wejścia opisany w poprzedniej sekcji, dzięki czemu wiele modułów podrzędnych nie będzie jednocześnie importować modułu
awaitnajwyższego poziomu, możesz bezpiecznie polegać na moduleawaitnajwyższego poziomu bez dodatkowego rozwiązania zastępczego. - Starsze przeglądarki (sprzed 2021 r.): jeśli Twoja aplikacja musi obsługiwać przeglądarki bez obsługi
awaitna najwyższym poziomie, unikajawaitna najwyższym poziomie i opakuj warunkową orkiestracjęimport()w standardową funkcjęasynclub łańcuch obietnic.then().