我读到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
JavaScript等1
之后2
,然后写3
。为什么132
?
答案 0 :(得分:8)
await
仅在传递给它的值为Promise
时暂停。在您的情况下,setTimeout
会返回Number
,因此请等待它。
正确的代码如下:
async function test() {
console.log('1');
await new Promise((resolve, reject) => {
setTimeout(() => {
console.log('2');
resolve()
}, 0);
});
console.log('3');
}
答案 1 :(得分:2)
因为setTimeout
没有返回承诺。 await x
仅在x
是承诺时才会等待;如果x
不是承诺,那么它(有效地)包含在一个承诺中,就好像你有await Promise.resolve(x)
一样。这意味着它后面的代码将尽快异步运行。*
如果您需要setTimeout
的承诺版本,请参阅this question's answers。但即使这样,你的test
函数也不会使用回调,而只是等待启用promise的超时:
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)
之前,因为任务期间安排的承诺回调发生在该任务结束后,在从队列中拾取下一个任务之前(即使下一个任务是在promise回调之前安排的)。更多关于this question's answers中的“macrotasks”和“microtasks”。
答案 2 :(得分:1)
您可以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');
})();