async / await
async/await — синтаксический сахар над промисами: компилятор разбивает функцию на microtask-шаги по каждому await, формируя конечный автомат; весь код до первого await выполняется синхронно — это меняет стек и порядок событий.
async function fetchData() { Трансформация в .then-цепочку:
const a = await step1(); ──→ step1()
const b = await step2(a); ──→ .then(a => step2(a))
return b + 1; ──→ .then(b => b + 1)
} .catch(propagate)
Точки разрыва выполнения (microtask границы):
sync await step1() await step2(a) return
│ │ │ │
──┼─────────────────┼─────────────────┼──────────────┼──→ время
│ microtask microtask microtask
│ (resume) (resume) (resolve)
│
└── весь код до первого await выполняется СИНХРОННО
(вызывающий код продолжается после этого)
// async функция ВСЕГДА возвращает Promiseasync function getValue() { return 42; }const p = getValue();console.log(p instanceof Promise); // truep.then(v => console.log(v)); // 42
// await работает на любом thenable (duck typing)const thenable = { then: (resolve) => resolve(99) };async function test() { const v = await thenable; console.log(v); // 99}
// Синхронная часть до первого await — обычный кодasync function sideEffect() { console.log('sync!'); // выполнится немедленно await delay(100); console.log('after delay');}sideEffect();console.log('after sideEffect call'); // sync! → after sideEffect call → after delay// Параллельный vs последовательный запуск — типичная ошибка
// BAD: последовательно (200ms + 100ms = 300ms)async function slow() { const user = await fetchUser(); // 200ms const posts = await fetchPosts(); // 100ms (ждёт user) return { user, posts };}
// GOOD: параллельно (~200ms)async function fast() { const [user, posts] = await Promise.all([fetchUser(), fetchPosts()]); return { user, posts };}
// Или: запустить промисы заранее, потом awaitasync function alsoFast() { const userP = fetchUser(); // стартует немедленно const postsP = fetchPosts(); // стартует немедленно return { user: await userP, posts: await postsP };}// await в цикле: sequential vs parallel vs batched
// Sequential (порядок важен / rate-limit):for (const id of ids) { await processItem(id); // каждый ждёт предыдущего}
// Parallel (все сразу):await Promise.all(ids.map(id => processItem(id)));
// Batched parallel (по N штук):async function batchProcess(items, batchSize = 5) { for (let i = 0; i < items.length; i += batchSize) { await Promise.all( items.slice(i, i + batchSize).map(processItem) ); }}Итог: async/await — синтаксический сахар над .then()-цепочкой; компилятор создаёт конечный автомат, каждый await — точка разрыва с возобновлением через microtask queue.