Top-level await cho phép dùng await trực tiếp ở cấp module (ngoài hàm async), chỉ trong ES module — không dùng được trong CommonJS hay script thường.
// db.js — ES module
const conn = await connect(process.env.DB_URL);
export { conn };Ảnh hưởng tới load order: một module có top-level await trở thành async module. Bất kỳ module nào import nó sẽ đợi nó settle xong rồi mới chạy phần body của mình — biểu đồ phụ thuộc tự động tuần tự hóa. Hình dung: module cha tạm "dừng" cho đến khi mọi dependency async đã sẵn sàng.
Dùng tốt cho:
- Khởi tạo phụ thuộc bất đồng bộ (DB connection, đọc config từ network) ngay tại module.
- Dynamic import có điều kiện: const mod = await import(condition ? './a.js' : './b.js').
- Fallback resource: await import('./fast.js').catch(() => import('./slow.js')).
Lưu ý (gotcha): nếu await chậm hoặc treo, nó chặn toàn bộ cây import phía dưới khởi động — đừng đặt việc nặng/không quan trọng ở top level. Lỗi reject ở top-level await làm việc evaluate module thất bại.
Top-level await lets you use await directly at module scope (outside an async function), only in ES modules — not in CommonJS or classic scripts.
// db.js — ES module
const conn = await connect(process.env.DB_URL);
export { conn };Effect on load order: a module with top-level await becomes an async module. Any module that imports it waits for it to settle before running its own body — the dependency graph serializes automatically. Picture the parent module "pausing" until every async dependency is ready.
Good for:
- Async initialization (DB connection, fetching config) right in the module.
- Conditional dynamic import: const mod = await import(cond ? './a.js' : './b.js').
- Resource fallback: await import('./fast.js').catch(() => import('./slow.js')).
Gotcha: a slow or hanging await blocks the whole downstream import tree from starting — don't put heavy/non-critical work at top level. A rejection at top-level await fails the module's evaluation.