#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
, которая вернет aPromise 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();
Попробуйте это. Вы можете добиться создания функции внутри своей основной функции, а затем поместить свой код обещания внутри этой функции. Вызовите его там, и когда вы получите ответ или ошибку, просто верните его.