Как ждать асинхронную функцию?
Мое дело:
let waiting = function () {
return new Promise(resolve => {
console.log('awaiting...');
setTimeout(function () {
resolve();
}, 1000)
});
};
let waitingAsync = async function () {
console.log('start...');
await waiting();
console.log('stop...');
};
waitingAsync();
console.log('done...');
В коде есть две вещи, которые я не понимаю:
Первый:
await waiting();
waiting
является синхронной функцией (потому что она не имеет async
ключевое слово). Итак, почему я могу ждать синхронную функцию?
Второй:
Почему не мог done...
сообщение будет ждать после завершения waitingAsync
функционировать?
И главный вопрос: waitingAsync
является асинхронной функцией, почему await
ключевое слово не требуется при вызове? Просто waitingAsync()
вместо await waitingAsync()
,
Если я могу ждать waitingAsync()
, done...
сообщение будет напечатано последним.
5 ответов
Это не функция, а возвращаемое значение, которое ожидается await
заявление.
async
и обычные функции не отличаются от вызывающего. async
просто возвращает обещание, не возвращая его явно при вызове. Результат waitingAsync()
Звонок это обещание. Результат waiting()
Вызов тоже обещание, поэтому оно не является "синхронным".
Согласно спецификации, как обещания, так и не обещания могут быть await
редактор Необещания преобразуются в обещания с Promise.resolve()
,
console.log('done...')
нельзя ожидать, потому что он не вызывается внутри async
функция. И это не должно быть await
Эд, потому что это не возвращает обещание, но undefined
, await
это было бы возможно в течение async
функция. Эти await
использования равны и в равной степени бесполезны, все, что они делают, это задержка на 1 такт:
async function ... {
...
await console.log('done...');
}
async function ... {
...
console.log('done...');
await undefined;
}
async function ... {
...
await Promise.resolve(console.log('done...'));
}
async
Функция возвращает обещание или, когда она использует await
ключевое слово, оно должно ждать асинхронную функцию, будь то обещание или другое async
функция. В вашем коде waiting()
это функция, которая возвращает обещание Затем, await waiting()
правильно (так как он ожидает асинхронной функции).
async
функция вызывается как другая базовая функция называется. Вы можете пометить функцию как асинхронную, если хотите использовать ее как асинхронную функцию и использовать ключевое слово "await". "Готово..." печатается, потому что, когда вы звоните asyncFunction()
, это должно await
до тех пор waiting promise
закончен. Но программа не останавливается и продолжает показывать done...
, Если вы хотите подождать, может быть, вы можете использовать asyncFunction().then( () => console.log('done...') )
Когда ты await
функция, если эта функция возвращает обещание, ее возвращаемое значение будет рассматриваться как обещание then
значение. Если обещание будет отклонено, оно будет приведено к ошибке. Если вызов функции возвращает что-то более ненадежное, чем await
тогда просто ничего.
С другой стороны, когда вы объявляете async
функции, ее возвращаемое значение будет возвращено как Обещание, и любая ошибка, сгенерированная из него, будет приведена к отклоненному Обещанию.
Ты можешь использовать await
только в пределах async
объявленная функция.
это только о async
а также await
есть, просто автоматическое приведение к обещаниям. Вам не нужно, чтобы код, использующий await и async, был действительно асинхронным (хотя, на самом деле, он не очень полезен).
Быстрая демонстрация:
//Will return the string 'Promise' if called through `await`
function getPromise(){
return Promise.resolve('Promise');
}
//Casted to Promise.reject thrught await
function throwError(){
return Promise.reject('error');
}
function get(){
return 'something simple';
}
async function getAsync() {
var response = await getPromise();
return response;
}
//await will cast the rejected Promise to an error
async function getErrorAsync() {
var response = await throwError();
return response;
}
async function simpleGet(){
return get();
}
async function redundantGet(){
return await get();
}
async function catchTheError(){
try{
await throwError();
}
catch(e){
console.log('an error: ' + e );
}
return 'whatever';
}
getAsync().then( console.log ); //Promise
getErrorAsync().catch( console.log ); //error
simpleGet().then( console.log ); //something simple
redundantGet().then( console.log ); //something simple
catchTheError(); //will log 'an error: error'.
Так:
ожидание - синхронная функция (потому что у нее нет ключевого слова async). Итак, почему я могу ждать синхронную функцию?
Потому что ты можешь. Единственная вещь await
делает, чтобы разрешить обещание реальных ценностей и ошибок. Вам на самом деле не нужна функция для возврата обещания.
Почему не удалось сделать... после завершения функции waitAsync можно ожидать сообщения?
async
а также await
только заставляет ваш код вести себя так, как если бы он был синхронным async
объявленные функции. Твоя последняя console.log('done')
вне любого async
функция, поэтому она будет просто записана в журнал до завершения этой функции, поскольку она асинхронная.
И главный вопрос: waitAsync - это асинхронная функция, почему ключевое слово await не требуется при ее вызове? Просто waitAsync() вместо await waitAsync().
Так как async
ключевое слово преобразует значения в обещания и позволяет использовать await
- и больше ничего. На самом деле, так как вы можете использовать только await
внутри async
функции... вы не можете ожидать async
функции для вызова await
Вам понадобится бесконечное количество async
функции:-D.
Async
ключевое слово, используемое для указания того, что функция будет экземпляром AsyncFunction
так что вернусь Promise
,
Await
используется для ожидания разрешения обещания внутри асинхронной функции.
Согласно асинхронной функции MDN может содержать await
выражение, которое приостанавливает выполнение асинхронной функции и ожидает разрешения переданного обещания, а затем возобновляет выполнение асинхронной функции и возвращает разрешенное значение.
В вашем сообщении много хороших вопросов, которые могут помочь понять асинхронные вызовы.
Прежде чем приступить к делу, стоит обратить внимание на несколько вещей.
Любой читатель фрагмента кода
let waiting = function () {
return new Promise(resolve => {
console.log('awaiting...');
setTimeout(function () { resolve(); }, 1000);
});
};
let waitingAsync = async function () {
console.log('start...');
await waiting();
console.log('stop...');
};
waitingAsync();
console.log('done...');
может ошибочно полагать, что результат будет
start...
awaiting...
stop...
done...
в то время как - как вы уже отметили - печатается перед
stop...
.
Причина в том, что
waitingAsync();
это вызов асинхронной функции, а
console.log('done...');
это просто нормальный последовательный / синхронный оператор, который выполняется сразу.
Вопрос 1:
является синхронная функция (потому что он не имеет
async
ключевое слово) [?]
Ответ :
Неверно.Функция является синхронной - она возвращает Promise .
Вопрос 2:
Почему после завершения функции нельзя было ожидать сообщения?
Ответ :
Потому что не асинхронный.
(Он не возвращает никаких обещаний.)
Вопрос 3:
И главный вопрос: это асинхронная функция, почему
await
ключевое слово не требуется при вызове?
Ответ :
Ну, в вашем примере не возвращает никакого значения. - Если бы возвращать значение , которое вы заботитесь о, то вам нужно будет ждать его , чтобы получить его. (
Hello world!
в моем фрагменте стека ниже.)
Вопрос 4:
Если я могу подождать
waitingAsync()
, [the]done...
сообщение будет напечатано последним. [?]
Ответ :
Это зависит от того, что именно вы имеете в виду. - См. Мой фрагмент стека ниже! Пока
done
сообщение находится в том же обратном вызове, что и вызов, ответ - Да!
Но если поставить
console.log('done...')
после асинхронного вызова, который завершает
await waitingAsync()
тогда ответ - нет!
При запуске приведенного ниже фрагмента обратите внимание на порядок вывода!
Также обратите внимание , как она занимает 1400 мс для
Promise resolved!
показывать.
Последняя асинхронная функция анонимна - без имени - и вызывается немедленно. Фактически, это единственная функция, которая вызывается непосредственно во фрагменте. Функция вызывается только в непосредственно ( с помощью анонимной функции), а функция
waiting
также называется косвенно (
waitingAsync
).
Урок на вынос
Никогда не помещайте последовательный / синхронный код после и вне вызова асинхронной функции!
Если вы это сделаете, вы просто запутаете себя. - И даже если вы не запутаетесь, другие читатели вашего кода почти наверняка будут.