Не должен ли асинхронный возврат Promise без явного переноса возвращаемого значения в Promise?
Документация MDN гласит, что
Когда асинхронная функция вызывается, она возвращает Promise. Когда асинхронная функция возвращает значение, Обещание будет разрешено с возвращенным значением. Когда асинхронная функция генерирует исключение или какое-либо значение, Обещание будет отклонено с брошенным значением.
Поэтому что я делаю не так, учитывая что await
ожидает решительного обещания?
foo();
async function foo(){
await bar();
zoo();
}
async function bar(){
setTimeout(() => {
console.log("bar");
return;
}, 1000);
}
function zoo(){
console.log("zoo");
}
В соответствии с тем, что я (неправильно) понял, он должен сначала войти bar
а потом zoo
, но ведёт себя наоборот.
РЕДАКТИРОВАТЬ: Теперь, благодаря разъяснениям от @Matt Morgan, я понимаю ошибку, как bar()
функция возвращает undefined
, Тем не менее, я думал, что позвонив async
сама по себе функция заставит функцию немедленно вернуть нерешенное обещание, и такое обещание будет разрешено, когда async
функция будет возвращать любое значение (даже неопределенное). Но теперь я понимаю, что действительно нужно вернуть обещание, объявив его return Promise
заявление. Я думаю, что статья MDN для async
, о котором я все это читал, немного запутывает эту тему (только мое мнение).
Поэтому я мог бы просто изменить свой bar()
функция для:
function bar(){
return new Promise(function(resolve){
setTimeout(() => {
console.log("bar");
resolve();
}, 1000);
});
}
1 ответ
bar()
устанавливает тайм-аут и возвращает значение undefined, что не совпадает с немедленным выполнением оператора регистрации, который запускается по истечении тайм-аута.
Так, zoo()
запускается, а затем, когда время ожидания истекает (через 1000 мс), вы видите "бар" в консоли.
Вот модифицированный пример без тайм-аута:
foo();
async function foo(){
await bar();
zoo();
}
async function bar(){
console.log("bar");
}
function zoo(){
console.log("zoo");
}
С нет setTimeout
, вы получите порядок исполнения вы ожидаете.
Второй пример, где у вас есть delay()
функция, которая оборачивает setTimeout
в обещании:
foo();
async function foo(){
await bar();
zoo();
}
async function bar(){
await delay();
console.log("bar");
}
function delay(t, v) {
return new Promise(function(resolve) {
setTimeout(resolve.bind(null, v), t)
});
}
function zoo(){
console.log("zoo");
}
Последний фрагмент кода ожидает разрешения обещания, так что вы видите bar
, затем foo
,
Выше delay
было взято с /questions/31655901/ispolzovanie-settimeout-v-tsepochke-obeschanij/31655924#31655924
Вот последний пример, где bar()
возвращает "бар". Это означает, что это завернуто в обещание async
декларация, и решается await
внутри foo()
Опять же, вы видите то, что ожидали увидеть.
foo();
async function foo(){
console.log(await bar());
zoo();
}
async function bar(){
return 'bar';
}
function zoo(){
console.log("zoo");
}
Важно понимать, что ваш оригинальный пример не возвращает значение bar
, Возвращается undefined
и если вы измените свой исходный код, чтобы выйти возвращенное значение bar()
в консоли вы увидите три вещи:
- Немедленно возвращенная форма обещания
bar()
который разрешаетundefined
, - Значение
zoo
отzoo()
функция. - Наконец, по истечении 1000 мс вы увидите
bar
вошел изsetTimeout
это было вытолкнуто в очередь.
Попробуйте, посмотрите, что вы получите.