#javascript #typescript #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
, которая возвращает aPromise Object
при вызове. Возьмемconst t = async () => { ... }
, к примеру,t
являетсяAsyncFunction Object
иt()
вернетPromise Object
3. Правильно, я хочу сказать, что формулировка сбивает с толку, возврата нет, она просто вычисляется как значение, которое является
AsyncFunction
, и эта функция имеет возврат.async function fn(){}
это объявление, оно ничего не возвращает, это просто функция ASYNC.4. Нужно ли мне явно возвращаться к асинхронному методу? как это будет, если я ничего не верну в асинхронном методе