为什么 `async/await` 在我的情况下不起作用?
Why `async/await` doesn't work in my case?
我读到了 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
?
您可以 await
使用 returns Promise
的功能。 setTimeout
没有 returns Promise
。所以在这种情况下 await
在 setTimeout
之前使用是没有意义的。
您可以将 setTimeout
包装到 Promise 中并在 setTimeout
函数中调用 resolve。
(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');
})();
因为 setTimeout
没有 return 承诺。 await x
只有在 x
是一个承诺时才会等待;如果 x
不是一个承诺,它会(有效地)包含在一个承诺中,就好像您有 await Promise.resolve(x)
一样。这意味着它后面的代码将 运行 异步但尽快。*
如果您想要 setTimeout
的承诺版本,请参阅 this question's answers。但即便如此,您的 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)
之前,因为在任务期间安排的 promise 回调发生在该任务结束之后,在从中拾取下一个任务之前队列(即使下一个任务是在 promise 回调之前安排的)。 this question's answers.
中的更多信息("macrotasks" 和 "microtasks")
await
只有当传递给它的值是 Promise
时才会挂起。在你的情况下,setTimeout
returns a Number
所以 await 不会等待它。
正确的代码如下:
async function test() {
console.log('1');
await new Promise((resolve, reject) => {
setTimeout(() => {
console.log('2');
resolve()
}, 0);
});
console.log('3');
}
我读到了 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
?
您可以 await
使用 returns Promise
的功能。 setTimeout
没有 returns Promise
。所以在这种情况下 await
在 setTimeout
之前使用是没有意义的。
您可以将 setTimeout
包装到 Promise 中并在 setTimeout
函数中调用 resolve。
(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');
})();
因为 setTimeout
没有 return 承诺。 await x
只有在 x
是一个承诺时才会等待;如果 x
不是一个承诺,它会(有效地)包含在一个承诺中,就好像您有 await Promise.resolve(x)
一样。这意味着它后面的代码将 运行 异步但尽快。*
如果您想要 setTimeout
的承诺版本,请参阅 this question's answers。但即便如此,您的 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)
之前,因为在任务期间安排的 promise 回调发生在该任务结束之后,在从中拾取下一个任务之前队列(即使下一个任务是在 promise 回调之前安排的)。 this question's answers.
await
只有当传递给它的值是 Promise
时才会挂起。在你的情况下,setTimeout
returns a Number
所以 await 不会等待它。
正确的代码如下:
async function test() {
console.log('1');
await new Promise((resolve, reject) => {
setTimeout(() => {
console.log('2');
resolve()
}, 0);
});
console.log('3');
}