асинхронность/ожидание всегда возвращает обещание

#javascript #node.js #debugging #async-await #promise

Вопрос:

Я пытаюсь использовать функцию асинхронности/ожидания. У меня есть такой код, имитирующий запрос:

 const getJSON = async () => {
  const request = () => new Promise((resolve, reject) => (
    setTimeout(() => resolve({ foo: 'bar'}), 2000)
  ));

  const json = await request();
  return json;
}
 

Когда я использую код таким образом

 console.log(getJSON()); // returns Promise
 

это возвращает обещание

но когда я вызываю эту строку кода

 getJSON().then(json => console.log(json)); // prints { foo: 'bar' }
 

он печатает json, как и ожидалось

Можно ли использовать просто такой код console.log(getJSON()) ? Чего я не понимаю?

Комментарии:

1. async/await always returns promise — это правильно, поскольку все помеченные функции async всегда будут возвращать обещание — в этом весь смысл асинхронности/ожидания

Ответ №1:

Каждая async функция возвращает Promise объект. await Оператор действует на a Promise , ожидая, пока Promise resolve s или reject s.

Так что нет, вы не можете console.log напрямую использовать результат асинхронной функции, даже если используете await . Использование await заставит вашу функцию подождать, а затем вернет Promise значение, которое немедленно разрешится, но оно не развернет Promise его для вас. Вам все равно нужно развернуть Promise возвращаемое async функцией, либо используя await , либо используя .then() .

Когда вы используете .then() console.log вместо прямого вызова, .then() метод делает результат Обещания доступным для вас. Но вы не можете получить результат Promise извне Обещания. Это часть модели работы с Обещаниями.

Комментарии:

1. Я думал, что весь смысл async/await в том, чтобы вы могли писать функции асинхронного обещания с использованием синхронного кода. Вы хотите сказать, что вам всегда нужно следить за async какой-либо функцией .then() ? Если да, то чем это отличается от простого использования Обещания само по себе?

2. Дело в том, что внутри async функции вы можете писать асинхронный код, как если бы он был синхронным. Однако, находясь вне async функции, вам необходимо обрабатывать асинхронный результат этой функции как обычно. Что обычно не является проблемой, так как в любом случае вы должны получать только асинхронные результаты в своей логике пользовательского интерфейса.

3. Подводя итог: вы пишете свою асинхронную логику так, как если бы она была синхронной, однако, когда вы вызываете свою асинхронную логику из кода, который на самом деле является синхронным, вам необходимо различать фактически синхронный и фактически асинхронный.

4. В дополнительных комментариях не было необходимости. Недостающий элемент заключался в том, что await просто распаковывает обещание так же, как это делает .then (), но то, что возвращается, снова завернуто в обещание. И это также означает, что весь синтаксический сахар return new Promise обрабатывается для вас, поэтому создание асинхронной функции делает это для вас бесплатно, и вам нужно только сейчас выбрасывать ошибки и использовать try / catch для отлова отклонений или ошибок (то же самое). Теперь все это имеет такой смысл, так что миллион благодарностей!

5. «Использование await заставит вашу функцию подождать, а затем вернет обещание, которое немедленно разрешится, но оно не развернет обещание для вас». разве оно не разрешится немедленно только в том случае, если редактируемая функция await может быть немедленно оценена? Как и в примере с операцией, обещание не решается сразу, так как оно занимает 2 секунды.

Ответ №2:

Функция, определенная с async помощью, всегда возвращает a Promise . Если вы вернете любое другое значение , которое не является a Promise , оно будет неявно заключено в a Promise . Оператор const json = await request(); разворачивает Promise возвращенное request() значение в обычный объект { foo: 'bar' } . Затем это завернуто в a Promise до того, как будет возвращено из getJSON так что a Promise -это то, что вы в конечном итоге получаете, когда звоните getJSON() . Поэтому, чтобы развернуть его, вы можете либо позвонить getJSON().then() , как вы это сделали, либо сделать await getJSON() , чтобы получить разрешенное значение.

Комментарии:

1. так много искажений и разворачиваний ИМХО, если вы сделаете свой ответ короче, это звучит многообещающе

2. IKR, я думаю, что основной вывод заключается в том, что возвращаемое значение асинхронной функции всегда является обещанием и поэтому должно использоваться с await/then для получения разрешенного значения.

Ответ №3:

Возвращаемое значение асинхронной функции всегда будет объектом AsyncFunction, который будет возвращать значение a Promise при вызове. Вы не можете изменить этот тип возвращаемого значения. Смысл async/await в том, чтобы легко дождаться завершения другого асинхронного процесса внутри асинхронной функции.

Комментарии:

1. Ваше первое предложение противоречиво, оно не может вернуть как Обещание, так и AsyncFunction объект.

2.@loganfsmyth, когда вы определяете асинхронную функцию, она возвращает a AsyncFunction Object , которая возвращает a Promise Object при вызове. Возьмем const t = async () => { ... } , к примеру, t является AsyncFunction Object и t() вернет Promise Object

3. Правильно, я хочу сказать, что формулировка сбивает с толку, возврата нет, она просто вычисляется как значение, которое является AsyncFunction , и эта функция имеет возврат. async function fn(){} это объявление, оно ничего не возвращает, это просто функция ASYNC.

4. Нужно ли мне явно возвращаться к асинхронному методу? как это будет, если я ничего не верну в асинхронном методе