@baranovstas

Как вывод в консоль дожидается выполнения async функции?

Всем привет. Есть следующий код:
async function func() {
  const response = await fetch('https://jsonplaceholder.typicode.com/users');
  return await response.json();
}
console.log(func()); // успешный промис, результат которого - массив пользователей

Что выполняется внутри func?
1) fetch возвращает промис.
2) Промис делает get запрос.
3) Получает ответ - объект Response.
4) Потом резолвится этим объектом.
5) Тем временем, await, перед fetch, ждёт выполнения всех 4 пунктов, чтобы получить результат промиса и отдать этот результат в const response.
6) Затем мы переводим результат из json-строки в массив - это тоже происходит не сразу, а с определённой задержкой.
7) Поэтому мы добавляем еще один await, чтобы дождаться и этой операции.
8) И вот только после того, когда все вышестоящие пункты выполнились, вот тогда и происходит return из func.

Но! Вывод в консоль - это синхронный код, а значит не ждёт выполнения всех пунктов (асинхронных операций). По сути для вывода в консоль тело func должно быть таким:
async function func() {
  const response = undefined; // undefined, потому что синхронный код не ждёт, когда придет ответ от сервера, он тупо идет дальше...
  return undefined; // тут тоже возвращается undefined, потому что вывод не ждёт выполнения - await response.json()
}
console.log(func()); // успешный промис с результатом undefined

И вот сам вопрос - почему выводится промис, результат которого массив? Почему не выводится промис с результатом undefined? То есть получается вывод в консоль успевает дождаться всех операций у func, верно?

Ремарка: я знаю, что async возвращает промис и резолвит его со значением, которое идёт после return (если после return идет промис, то возвращается он). А если у функции нет конкретного возвращаемого значения или вообще, её тело пустое, то вернётся успешный промис с результатом undefined.
  • Вопрос задан
  • 348 просмотров
Пригласить эксперта
Ответы на вопрос 2
Rsa97
@Rsa97
Для правильного вопроса надо знать половину ответа
async func() всегда возвращает промис.
И в консоль выводится именно этот промис со статусом pending.
После завершения fetch и json статус промиса изменится на fulfilled и ему добавится значение.
Вот вывод консоли сразу после console.log:
Promise { <state>: "pending" }
Если через некоторое время раскрыть этот объект, то увидим, что его статус уже сменился (вы ведь помните, что в консоль выводится живой объект по ссылке):
Promise { <state>: "pending" }
​  <state>: "fulfilled"
​  <value>: Array(10) [ {…}, {…}, {…}, … ]
​  <prototype>: Promise.prototype { … }
Ответ написан
@zkrvndm
Софт для автоматизации
Асинхроная функция всегда возвращает промис, вы своим console.log выводите отнюдь не результат, а тупо промис от функции. Далее, в консоли вполне можно запускать асинхронный код, попробуйте прямо сейчас вбить в консоли:
response = await (await fetch('https://jsonplaceholder.typicode.com/users')).json();
console.log(response);

Или же применительно к вашему коду делайте так:
async function func() {
  const response = await fetch('https://jsonplaceholder.typicode.com/users');
  return await response.json();
}
console.log(await func());
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы