تسمح ميزة 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ذات المستوى الأعلى من وحدات شقيقة متعددة في الوقت نفسه (على سبيل المثال، استيراد./conditionally-load-polyfill.jsبشكل ثابت من كل منa.jsوb.js). على الرغم من أنّ الإصدار 27 من Safari قد أصلح أداة تحميل الوحدات في WebKit لإتاحة عمليات الاستيراد المتزامنة لوحداتawaitذات المستوى الأعلى وفقًا للمواصفات، فإنّ الإصدارات من 15 إلى 26.6 من Safari تتعطّل عندما تستورِد وحدات متعددة في الوقت نفسه وحدة تحتوي على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).
- الإصدارات من 15 إلى 26.6 من Safari: طالما أنّك تتّبع نمط نقطة الدخول الواحدة في القسم السابق، لن تستورد وحدات تابعة متعددة وحدة
awaitذات المستوى الأعلى في الوقت نفسه، ويمكنك الاعتماد بأمان علىawaitذات المستوى الأعلى بدون استخدام إجراء احتياطي إضافي. - المتصفّحات القديمة (ما قبل 2021): إذا كان تطبيقك يتطلب دعم المتصفّحات التي لا تتضمّن أي دعم لـ
awaitعلى المستوى الأعلى، تجنَّب استخدامawaitعلى المستوى الأعلى وغلِّف تنسيقimport()الشرطي في دالةasyncعادية أو سلسلة وعود.then().