Расскажите про асинхронность в JavaScript и средства работы с асинхронным кодом
Что проверяют
Понимаете ли вы event loop и очереди задач, а не только синтаксис async/await. Следом почти всегда идёт задача на порядок вывода.
Как отвечать
JavaScript однопоточный: один стек вызовов. Асинхронность обеспечивает не язык, а окружение. Браузер или Node отдают долгие операции своим API, а результат возвращают в очередь, откуда его забирает event loop, когда стек пуст.
Очередей две, и это главное:
- микрозадачи: промисы,
queueMicrotask,MutationObserver. Выполняются полностью после текущей синхронной работы, до следующей макрозадачи; - макрозадачи:
setTimeout, события, ввод-вывод.
setTimeout(() => console.log("timeout"), 0);
Promise.resolve().then(() => console.log("promise"));
console.log("sync");
// sync, promise, timeoutСредства по мере развития: колбэки (отсюда вложенность и «ад колбэков»), промисы (then, catch, finally, композиция через all, allSettled, race, any), async/await как синтаксис поверх промисов, асинхронные итераторы и for await.
Практическое: независимые операции запускают через Promise.all, а не последовательными await, иначе время складывается вместо максимума. Отмена делается через AbortController.
Где спотыкаются
Считают, что async создаёт поток. Потока нет, есть очередь и передача работы окружению.
Пишут await в цикле по независимым элементам и получают линейное время.
Не различают Promise.all (падает на первой ошибке) и allSettled (дожидается всех).
Забывают, что forEach не ждёт асинхронный колбэк, и цикл заканчивается раньше работы.