我看到了很多
setTimeout
即使使用 await
关键字也不等待的问题,答案就像将它与 promise
一起使用,但我仍然不明白。
async
函数不是隐式返回promise
吗?那么,从下面的代码中,函数 f
里面有一个 setTimeout
返回承诺?并且可以与 await
关键字一起使用。
const f = async(x) => {
setTimeout(() => {
console.log(x, 'done!!!')
}, x)
}
(async() => {
await f(2000)
await f(1000)
await f(500)
console.log('all done!')
})()
我的预期结果:
2000 已完成!!!
1000 已完成!!!
500 已完成!!!
全部完成!
const f = async(x) => {
setTimeout(() => {
console.log(x, 'done!!!')
}, x)
}
(async() => {
await (async() => {
f(2000)
f(1000)
f(500)
})()
console.log('all done!')
})()
我的预期结果:
500 已完成!!!
1000 已完成!!!
2000 已完成!!!
全部完成!
异步函数不是隐式返回promise吗?
是的,通过创建一个函数
async
,该函数将返回一个承诺。但如果您的代码中没有任何 await
,则该承诺将立即得到解决。
让我们逐步执行此代码:
async (x) => {
setTimeout(()=>{console.log(x, 'done!!!')}, x)
}
函数开始运行。它调用
setTimeout
,要求 javascript 在 x 毫秒过后调用函数 () => {console.log(x, 'done!!!')}
。 JavaScript 会记录此请求,并且您的函数将继续。没有更多的代码行,因此您的功能已完成。它隐式返回一个未定义的值,它被包裹在一个承诺中。
最终结果:计时器已启动,但尚未完成,调用
f
的人都会收到处于已解决状态的 Promise。所以 await
这个承诺不会造成任何延迟,因为承诺已经解决了。一段时间后,超时将会消失,console.log 也会发生,但这并不影响 f
返回的 Promise 何时解析。
如果您想设置超时并将其包装在 Promise 中,请使用
new Promise
构造函数:
const f = (x) => {
return new Promise((resolve, reject) => {
setTimeout(() => resolve(), x);
});
}
// Or shorter:
const f = (x) => {
return new Promise((resolve) => {
setTimeout(resolve, x);
});
}
当此版本的
f
运行时,您开始创建一个新的 Promise。在构建 Promise 时,您设置了超时并要求 javascript 在 x 毫秒后调用函数。然后你返回这个处于待处理状态的承诺。等待这个承诺将导致您的代码暂停。一段时间后,超时结束,您调用resolve。现在承诺已经解决,因此等待它的任何代码都可以继续。