Можно ли считать async/await синтаксическим сахаром над промисами?
Что проверяют
Понимаете ли вы, что await не останавливает поток, а подписывается на промис и возвращает управление событийному циклу. Ответ «да, сахар» без объяснения механики засчитывают редко.
Как отвечать
Да, это надстройка над промисами, ничего нового в рантайм она не приносит. Точнее так: async функция всегда возвращает промис, return 5 из неё даёт выполненный промис, throw даёт отклонённый. await берёт значение, приводит его к промису и ставит продолжение функции в очередь микрозадач, поэтому даже await 1 на обычном числе откладывает выполнение до следующего тика.
async function load(id) {
const res = await fetch(`/api/items/${id}`);
return res.json();
}
// примерно то же самое
function load(id) {
return fetch(`/api/items/${id}`).then((res) => res.json());
}try/catch вокруг await соответствует .catch, блок finally соответствует .finally. Стоит назвать и то, чего у промисов нет: читаемые стек-трейсы, for await...of для асинхронных итераторов, top-level await в модулях. Плюс await работает с любым объектом, у которого есть метод then, а не только с настоящим промисом.
Где спотыкаются
Пишут два независимых await подряд и получают последовательные запросы там, где хватило бы Promise.all. Время ожидания складывается вместо того, чтобы браться по самому долгому.
Теряют ошибку на границе. return doWork() внутри try не перехватывается этим же catch, потому что функция уже вернула промис, нужен return await. Та же история с forEach: асинхронный колбэк никто не ждёт, и цикл заканчивается раньше работы.
Считают, что await замораживает всё вокруг. Он отдаёт управление циклу, и пока промис не выполнен, успевают отработать обработчики, таймеры и другие запросы. Поэтому состояние, прочитанное до await, после него перепроверяют.