وابستگی‌های غیرهمگام شرطی

ویژگی‌های وب: Top-level await

await سطح بالا به پیمانه‌ها اجازه می‌دهد به‌عنوان توابع ناهمگام عمل کنند، یعنی می‌توانند اجرای پیمانه را برای انتظار برای وعده‌ها متوقف کنند. این ویژگی برای بار کردن مشروط وابستگی‌های ناهمگام (مانند شبیه‌سازهای مرورگر یا کتابخانه‌های ثانویه سنگین) فقط درصورت نیاز مرورگر بسیار مفید است.

بااستفاده از await سطح بالا، می‌توانید منطق بارگیری شرطی را در یک واحد منفرد کپسوله کنید و به‌طور مؤثر از اجرای واحدهای مصرف‌کننده پایین‌دست تا زمانی که وابستگی کاملاً بارگیری و آماده شود جلوگیری کنید.

الگوی شبیه‌ساز مرورگر شرطی

درحالی‌که می‌توان از await سطح بالا برای بار کردن مشروط هر وابستگی ناهمگام که یک ماژول است استفاده کرد، یک کاربرد خوب از الگوی بار کردن وابستگی مشروط، بار کردن مشروط شبیه‌سازهای مرورگر برای مرورگرهایی است که از یک ویژگی خاص پشتیبانی نمی‌کنند. این رویکرد، تشخیص ویژگی و وارد کردن پویا را در یک واحد وابستگی واحد کپسوله می‌کند.

در مورد زیر، شبیه‌ساز مرورگر مشخصه 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 به‌طور هم‌زمان در همه مرورگرها قبل‌از اتمام بارگیری شبیه‌ساز مرورگر ارزیابی می‌شود.
  • پیمانه await سطح بالا را به‌طور هم‌زمان از چند پیمانه هم‌رده وارد نکنید (برای مثال، وارد کردن ایستا ./conditionally-load-polyfill.js توسط هر دو a.js و b.js). اگرچه Safari 27 بارکننده پیمانه WebKit را اصلاح کرد تا از وارد کردن هم‌زمان پیمانه‌های await سطح بالا طبق مشخصات پشتیبانی کند، Safari 15–26.6 وقتی چند پیمانه به‌طور هم‌زمان پیمانه‌ای حاوی await سطح بالا را وارد می‌کنند با شکست مواجه می‌شود (به سازگاری مرورگر MDN مراجعه کنید).

درعوض، یکی از دو الگو را بسته به ساختار واحدتان انتخاب کنید:

  1. واحد ورودی تکی (در main.js بالا نشان داده شده است): اگر واحد ورودی شما منطق مقداردهی اولیه وابسته را مستقیماً اجرا می‌کند، ./conditionally-load-polyfill.js را به‌صورت ایستا در بالای آن واحد وارد کنید و کدتان را در بدنه آن اجرا کنید.
  2. راه‌اندازی مدول‌های برنامه جداگانه: اگر مدول ورودی شما به مدول‌های برنامه پایین‌دست (مانند ./app.js) واگذار می‌شود، تماس‌های import() پویا را با await سطح بالا زنجیره‌ای کنید تا ./app.js فقط پس‌از حل شدن مدول شبیه‌ساز مرورگر واکشی و ارزیابی شود:
// 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 سطح بالای پایه از سال ۲۰۲۱ در مرورگرهای اصلی (Chrome 89،‏ Edge 89،‏ Firefox 89، و Safari 15) پشتیبانی می‌شود، تنها در Safari 27 به انطباق کامل با مشخصات رسید (به سازگاری مرورگر MDN مراجعه کنید).

  • Safari 15–26.6: تا زمانی که از الگوی نقطه ورودی واحد در بخش قبلی پیروی کنید تا چندین واحد هم‌نیا به‌طور هم‌زمان واحد سطح بالای await را وارد نکنند، می‌توانید بدون نیاز به بازگشت اضافی، به‌طور ایمن به await سطح بالا تکیه کنید.
  • مرورگرهای قدیمی (قبل‌از ۲۰۲۱): اگر برنامه شما باید از مرورگرهای فاقد پشتیبانی await سطح بالا پشتیبانی کند، از await سطح بالا اجتناب کنید و هماهنگ‌سازی import() شرطی خود را در یک تابع استاندارد async یا زنجیره وعده .then() قرار دهید.