Почему async функция возвращает Promise
Что проверяют
Понимаете ли вы, что async и await это синтаксис поверх промисов, а не отдельный механизм.
Как отвечать
Потому что функция обязана вернуть значение немедленно, а результат к этому моменту ещё не готов. Единственное, что можно отдать сразу, это обещание будущего результата.
Механика: async перед функцией по определению оборачивает её результат в промис. Обычный return 5 внутри превращается в промис, разрешённый значением 5; throw превращается в отклонённый промис. Возврат промиса из async функции не создаёт вложенности, он разворачивается.
await внутри это не пауза потока, а точка выхода: функция приостанавливается, управление возвращается вызывающему коду, а продолжение планируется микрозадачей на разрешение ожидаемого промиса. Ждать поток не может, он один.
Практические следствия:
- вызов
asyncфункции безawaitили.thenтеряет ошибку: получится необработанное отклонение промиса; asyncфункция синхронной не станет: даже без единогоawaitвнутри вызывающий получит промис;- обработчик события не стоит делать
asyncбездумно: возвращённый промис никто не ждёт, ошибки уходят в никуда; awaitв цикле последователен: независимые запросы запускают черезPromise.all.
Полезно упомянуть, что await работает не только с промисами, а с любым «thenable» объектом, у которого есть метод then. Именно поэтому старые библиотеки со своими обещаниями работают с await без переделки.
Где спотыкаются
Считают, что await блокирует поток.
Пишут return await в конце функции, не понимая, зачем это нужно (только для попадания в try/catch).
Ставят await в цикле там, где нужен Promise.all.
Не ловят ошибки из async обработчиков событий.