gpt4 book ai didi

javascript - 在循环中使用 Promise

转载 作者:行者123 更新时间:2023-11-30 11:13:23 24 4
gpt4 key购买 nike

我想了解这段代码是如何工作的。我已经使用 promise 工作了一段时间,但我想知道这里发生了什么。

for(let i=0 ; i< 3 ;i++){
new Promise((resolve,reject)=>{
console.log("i = "+i)
resolve(i)
})
.then(r=>{
console.log("promise 1 of "+r)
return new Promise((res,rej)=>res(r))
})
.then(r=>{
console.log("promise 2 of "+r)
return new Promise((res,rej)=>res(r))
})
}

console.log("finish")

输出是

i = 0 
i = 1
i = 2
finish
promise 1 of 0
promise 1 of 1
promise 1 of 2
promise 2 of 0
promise 2 of 1
promise 2 of 2

为什么在其他 promise 执行之前显示完成。

提前致谢

最佳答案

Why is finish being displayed before the other promises left to execute.

因为该代码中没有任何内容告诉 console.log 在运行之前等待 promise 完成。如果你想这样做,将它们收集在一个数组中,然后使用:

Promise.all(theArray)
.then(() => {
console.log("finish");
});

...告诉它等待他们。

请记住,then 处理程序总是 被异步调用。因此,您的代码创建了三个 promise 链,然后在末尾输出 console.log,然后将异步回调获取到 then 处理程序 - 所以这些结果会在之后显示。


旁注:您问题中的代码可以更简单地写成这样:

for(let i = 0; i < 3; i++) {
console.log("i = " + i);
Promise.resolve(i)
.then(r => {
console.log("promise 1 of " + r);
return r;
})
.then(r => {
console.log("promise 2 of " + r);
return r;
});
}

console.log("finish");

为什么:

  • promise 的执行函数(您传递给构造函数的函数)是同步运行的,因此 console.log("i = "+ i); 之间没有区别。 行作为执行程序函数的第一行,或者就在您创建 promise 的行之上。
  • Promise.resolve 使用您提供的值创建已解决的 promise 。
  • then always 创建一个新的 promise 。当您从 then 处理程序返回一个非 promise 值时,该值是 promise then 返回的解析值。如果您返回一个 promise ,那么 then 创建的 promise 将“从属于”您返回的 promise (等待它解决或拒绝,然后执行相同的操作)。

在评论中你问了一个非常聪明的问题:

If "then" is called asynchonously then the output order of these promises may not be predicted right?

要点:then 不是异步调用的,它的处理程序(您传递给它的函数)是异步调用的。

在一般情况下,是的,没错,您无法预测独立 promise (没有链接在一起的 promise )的顺序。您可以预测 链接在一起的 promise (链中较早的 promise 在较晚的 promise 之前处理)。在您的代码中,您有三个独立的链(一个用于 i = 0,一个用于 i = 1,另一个用于 i = 2);每个链都有两个处理程序(“1 of”和“2 of”)。所以你知道链“i = 0”中的“1 of”将在同一链中的“2 of”之前发生,但在一般情况下你不知道 i = 0 是否会成为第一个或 i = 2 一个或其他。

但是,在这种特定情况下,可以预测顺序(至少在浏览器中,在 Node.js 上也是如此),因为每个链中的初始 promise 开始out pre-resolved,这意味着当您调用 then 时,对其 then 处理程序的调用会立即放入微任务队列¹。微任务队列在每个任务(又名“宏任务”)结束时运行。因此,运行主代码的任务会立即按顺序将回调排队到每个链的“1 of”处理程序。当该处理程序运行时,它会将微任务排队以调用“2 of”处理程序。因此,由于 promises 开始得到解决,我们知道我们会得到您得到的输出。但在一般情况下,你是对的,你无法预测 链。

¹ 这是它的网络术语; JS 规范将其称为 PromiseJobs 队列。更多关于“微任务”和任务/宏任务的信息,请参阅 this answer .

关于javascript - 在循环中使用 Promise,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52664536/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com