await ברמה העליונה מאפשר למודולים לפעול כפונקציות אסינכרוניות, כלומר הם יכולים להשהות את ביצוע המודול כדי להמתין להבטחות. זה שימושי מאוד לטעינה מותנית של יחסי תלות אסינכרוניים, כמו polyfills או ספריות משניות כבדות, רק כשהדפדפן דורש זאת.
באמצעות שימוש ב-await ברמה העליונה, אתם יכולים להכיל את הלוגיקה של הטעינה המותנית בתוך מודול אחד, וכך למנוע ביעילות ממודולים של צרכנים במורד הזרם לפעול עד שהתלות נטענת במלואה ומוכנה.
תבנית polyfill מותנית
אפשר להשתמש ב-await ברמה העליונה כדי לטעון באופן מותנה כל תלות אסינכרונית שהיא מודול, אבל שימוש טוב בתבנית הטעינה המותנית של תלויות הוא לטעון באופן מותנה polyfills לדפדפנים שלא תומכים בתכונה ספציפית. הגישה הזו כוללת זיהוי תכונות וייבוא דינמי בתוך מודול תלות אחד.
במקרה הבא, ה-polyfill של המאפיין popover נטען באופן מותנה אם הוא לא קיים ב-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();
}
ייבוא מודולים ברצף והימנעות מהבאג בגרסאות Safari שקדמו לגרסה 27
חובה: צריך לבנות את תרשים המודולים כך שהמודול await ברמה העליונה ייובא מנקודת כניסה אחת ויושלם לפני שהמודולים הבאים בתור יעברו הערכה:
- אל תמקמו ייבואים סטטיים של אחים בקובץ כניסה (לדוגמה,
import './conditionally-load-polyfill.js'; import './app.js';). בהתאם למפרט ההערכה של מודול ECMAScript, awaitברמה העליונה משעה רק את מודול ההורה שמייבא אותו – לא ייבואים סטטיים של אחים – כך ש-./app.jsיעריך בו-זמנית בכל הדפדפנים לפני שה-polyfill יסיים להיטען. - אל תייבאו את המודול
awaitברמה העליונה מכמה מודולים אחים בו-זמנית (לדוגמה, גםa.jsוגםb.jsמייבאים באופן סטטי את./conditionally-load-polyfill.js). ב-Safari 27 תוקן טוען המודולים של WebKit כדי לתמוך בייבוא בו-זמני של מודוליםawaitברמה העליונה לכל מפרט, אבל ב-Safari 15-26.6 הייבוא נכשל כשכמה מודולים מייבאים בו-זמנית מודול שמכילawaitברמה העליונה (ראו תאימות לדפדפנים של MDN).
במקום זאת, בוחרים באחת משתי התבניות בהתאם למבנה המודול:
- מודול נקודת כניסה יחידה (מוצג ב-
main.jsלמעלה): אם מודול נקודת הכניסה מריץ את לוגיקת האתחול התלויה ישירות, מייבאים באופן סטטי את./conditionally-load-polyfill.jsבחלק העליון של המודול הזה ומריצים את הקוד בגוף שלו. - אתחול מודולים נפרדים של אפליקציות: אם מודול הכניסה שלכם מעביר למודולים של אפליקציות במורד הזרם (כמו
./app.js), צריך לקשר קריאות דינמיות שלimport()עםawaitברמה העליונה, כך ש-./app.jsיאוחזר ויוערך רק אחרי שמודול ה-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');
אסטרטגיות חלופיות
למרות שהדפדפנים המובילים תומכים ב-await בסיסי ברמה העליונה מאז 2021 (Chrome 89, Edge 89, Firefox 89 ו-Safari 15), הוא עמד בדרישות המפרט המלאות רק ב-Safari 27 (מידע נוסף זמין במאמר בנושא תאימות דפדפנים ב-MDN).
- Safari 15–26.6: כל עוד אתם פועלים לפי דפוס נקודת הכניסה היחידה שבקטע הקודם, כך שמספר מודולים אחים לא מייבאים בו-זמנית את המודול
awaitברמה העליונה, אתם יכולים להסתמך בבטחה עלawaitברמה העליונה בלי חלופה נוספת. - דפדפנים מדור קודם (לפני 2021): אם האפליקציה צריכה לתמוך בדפדפנים בלי תמיכה ב-
awaitברמה העליונה, צריך להימנע מ-awaitברמה העליונה ולעטוף את התזמור המותנה שלimport()בפונקציה רגילה שלasyncאו בשרשרת הבטחות של.then().