async / await всегда возвращает обещание

#javascript #node.js #reactjs #express #async-await

#javascript #асинхронный #обещание #async-await #ecmascript-2017

Вопрос:

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

 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 всегда будут возвращать обещание — в этом весь смысл async / await

Ответ №1:

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

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

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

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

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

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

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

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

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

Ответ №2:

Функция , определенная с async помощью , всегда возвращает a Promise . Если вы возвращаете любое другое значение , которое не является a Promise , оно будет неявно обернуто в a Promise . Оператор const json = await request(); разворачивает Promise возвращенное by 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(){} это объявление, оно ничего не возвращает, это просто асинхронная функция.

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

Ответ №4:

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

    const json = await request();
    return json;
  };
  return callAsyncCodeHere()
   .then(console.log)
   .catch(console.log);
};

getResOrErr();
 

Попробуйте это. Вы можете добиться создания функции внутри своей основной функции, а затем поместить свой код обещания внутри этой функции. Вызовите его там, и когда вы получите ответ или ошибку, просто верните его.