Что происходит при запуске функции с промисами и почему результат может быть пустым?
Что проверяют
Понимаете ли вы, что асинхронная функция возвращает управление раньше, чем появляются данные, и умеете ли по коду найти место, где результат теряется. Почти всегда следом дают фрагмент с console.log и просят назвать порядок вывода.
Как отвечать
Сначала модель выполнения. Функция-исполнитель в new Promise(...) выполняется синхронно, а колбэки .then, .catch и продолжение после await уходят в очередь микрозадач. Она разбирается, когда опустеет стек вызовов, и раньше очередной макрозадачи вроде setTimeout. Поэтому console.log(1); setTimeout(() => console.log(2)); Promise.resolve().then(() => console.log(3)); console.log(4) печатает 1, 4, 3, 2.
У промиса три состояния: pending, fulfilled, rejected, и сменить состояние он может ровно один раз.
Откуда берётся пустой результат:
- чтение раньше времени: переменная заполняется внутри
.then, а читается синхронно следующей строкой, когда там ещё пусто; - забытый
await: в переменной оказывается объектPromise {<pending>}, а не данные; - забытый
return: в цепочке.thenили в функции безreturnследующий шаг получаетundefined; forEachсasyncколбэком: он не ждёт промисы, массив результатов возвращается пустым. Нуженawait Promise.all(items.map(async ...))или циклfor...ofсawait;- проглоченная ошибка:
.catch(e => console.error(e))ничего не возвращает, и цепочка продолжается сundefined; fetchбез проверки: на 404 и 500 он не отклоняется, нужно смотретьresponse.ok, аresponse.json()тоже возвращает промис.
Для нескольких запросов назовите разницу: Promise.all отклоняется на первой ошибке, Promise.allSettled дожидается всех и отдаёт статус каждого.
Где спотыкаются
Ставят console.log(state) сразу после setState в React и считают, что запрос вернул пустоту. На деле новое значение появится только в следующем рендере.
Путают порядок микро- и макрозадач и уверенно ставят setTimeout(..., 0) раньше .then.
Оборачивают всё в try/catch без await внутри. Отклонённый промис из такого блока не ловится, и ошибка уходит в unhandledrejection.