Почему `async/await` не работает в моем случае?
Я читаю о async/await
, но у меня есть критический вопрос. Сначала я объясняю старый пример, чтобы показать базу моего вопроса, а затем задаю свой точный вопрос.
Все это знают:
console.log('1');
console.log('2');
console.log('3'); // Ex: 123
Это просто, но в следующем случае:
console.log('1');
setTimeout(()=>{
console.log('2');
},0);
console.log('3'); // Ex: 132
Это тоже просто, setTimeout
функция asynchronous
а также JavaScript
спрыгнуть с него и после разрешения запустить его функцию, так что мы видим 2
после 1
а также 3
,
Но теперь я читаю async/await
и я написал такую функцию:
(async function test() {
console.log('1');
await setTimeout(()=>{
console.log('2');
},0);
console.log('3');
})(); // Ex: 132
Экспорт 132
тоже почему? это мой вопрос, почему 3
беги раньше 2
? Я ожидаю из-за async/await
после 1
JavaScript ждет 2
а потом написал 3
, Зачем 132
?
3 ответа
await
только приостанавливается, когда переданное ему значение является Promise
, В твоем случае, setTimeout
возвращает Number
так что ждите, не ждите этого.
Правильный код будет следующим:
async function test() {
console.log('1');
await new Promise((resolve, reject) => {
setTimeout(() => {
console.log('2');
resolve()
}, 0);
});
console.log('3');
}
Так как setTimeout
не возвращает обещание. await x
ждет только если x
это обещание; если x
это не обещание, оно (эффективно) заключено в один, как будто вы await Promise.resolve(x)
, Это означает, что код, следующий за ним, будет работать асинхронно, но как можно скорее.*
Если вы хотите обещанную версию setTimeout
см . ответы на этот вопрос. Но даже с этим, ваш test
функция не будет использовать обратный вызов, вместо этого вы просто будете ждать тайм-аут с включенным обещанием:
function later(delay) {
return new Promise(function(resolve) {
setTimeout(resolve, delay);
});
}
async function test() {
console.log("1");
await later(10);
console.log("2");
console.log("3");
}
test().catch(e => console.error(e));
console.log("After the call (just to prove it does wait for the timeout after 1 and before 2");
* В браузерах это гарантированно будет до setTimeout(..., 0)
запланировано во время той же задачи, потому что обратные вызовы обещания, запланированные во время задачи, происходят сразу после окончания этой задачи, до того, как следующая задача будет выбрана из очереди (даже если следующая задача была запланирована до обратного вызова обещания). Подробнее об этом ("макрозадачи" и "микрозадачи") в ответах на этот вопрос.
Вы можете await
к тем функциям, которые возвращаются Promise
, setTimeout
не возвращается Promise
, Так что в этом случае await
используется до setTimeout
не имеет смысла.
Вы можете обернуть setTimeout
в обещание и позвонить решить на setTimeout
функция.
(async function test() {
console.log('1');
await new Promise((resolve, reject) => {
setTimeout(() => {
console.log('2');
resolve(); // also can pass a parameter here to get it via await.
},0);
});
console.log('3');
})();