【发布时间】:2021-08-29 19:32:08
【问题描述】:
(英语不是我的母语,所以如果你发现任何英语,请提前原谅我)
在这一点上,我对 Promises 和 Async await 函数非常满意,我也知道如何使用 Promise.all(它只是等待里面的所有 Promise 先解决,然后从所有 Promise 中提取值,然后使用带有这些值的 .then 函数返回一个数组。)
现在我想知道 for await of work 是怎么做的。
我刚刚写了这段代码:
async function f() {
let p1 = new Promise(function (r) {
setTimeout(r, 3000, 1)
})
let p2 = new Promise(function (r) {
setTimeout(r, 2000, 2)
})
let p3 = new Promise(function (r) {
setTimeout(r, 1000, 3)
})
let arrayOfPromises = [p1, p2, p3];
for await (let p of arrayOfPromises) {
let data = await p;
console.log(data)
}
}
f();
现在我的问题是,当它到达第一次迭代时会发生什么,它将到达一个 await 关键字,并且 await 立即返回一个待处理的承诺,那么下面的代码在技术上是否会在每次迭代中被评估为待处理的承诺?
{
let data = await p;
console.log(data)
}
所以我很困惑到底发生了什么,对于第一次迭代,setTimeout 将注册 3 秒,第二次注册 2,第一次注册 1。由于我们没有同步代码,所有的回调都会一个一个地运行,p3会先被解析,然后是p2,最后是p1!
现在直觉上我会认为一旦 p1、p2、p3 被解析,这段代码“console.log(data)”将被放入微任务队列,因为我们的 p3 先被解析,我们应该得到 3,2,1但是我们得到 1、2、3,那么我的理解中缺少什么?
(显然代码没有被放入微任务队列,它的函数可能会像生成器函数一样执行类似 .next() 的操作,但我认为这无关紧要)
似乎与 for await of 相比,第一个 Promise 将首先被记录,无论它与迭代中的其他 Promise 相比解决得有多快或多晚,那么到底发生了什么?
【问题讨论】:
-
await不返回承诺。它等待承诺被解决。 -
即使 promise 可能被解决,日志不会发生,直到你的 for 循环评估 promise。所以你的第一个承诺等待三秒钟,然后解决你的第一个循环。这时候,其他人也都解决了。尝试使您的第一个解析为 500 和第二个解析为 1000,您将看到它们之间的 500 毫秒延迟。简而言之,它按顺序检查它们。解决的时间不完全是 for 循环问题。
-
await p是多余的。在循环同步迭代器时,for await在分配给p之前会自动等待。 -
@Barmar - 嘿,但只要首先遇到等待,异步函数就会返回默认承诺,不是吗?就像在这段代码中一样: async function f(){ let d = await something(); // 此时,一个待处理的 Promise 已经返回 // 我们剩下的任何代码都将在我们等待的 Promise 解决后运行 } 这不正确吗?
标签: javascript for-loop asynchronous async-await promise