为啥一个已解决的承诺仍处于待处理状态?

Posted

技术标签:

【中文标题】为啥一个已解决的承诺仍处于待处理状态?【英文标题】:Why a resolved promise still in pending state?为什么一个已解决的承诺仍处于待处理状态? 【发布时间】:2022-01-20 00:08:02 【问题描述】:

例子:

let a = Promise.resolve("123")
        .then(val => 
                console.log(a);
                return 100;
        )
        .then(val => 
                console.log(val);
                console.log(a);
        )
        .finally(() => 
                console.log(a);
        );

输出:

Promise  <pending> 
100
Promise  <pending> 
Promise  <pending> 

为什么一个已解决的承诺仍处于待处理状态?

【问题讨论】:

RTFM。您正在返回一个可行的解决方案。 您能澄清一下为什么您认为您不会在这里看到待处理的内容吗? a的值是整个链中最后一个promise的promise,直到链中的所有.thens都解析后才能解析。你认为a 是链中的第一个承诺吗?在整个事情解决后尝试打印console.log(a);例如await a 在下一行,然后打印出来。 【参考方案1】:

所以,a 包含执行所有这些的结果:

let a = Promise.resolve(...).then(...).then(...).finally(...);

该阶段的每一步都会创建一个新的承诺,a 包含链中的最后一个承诺(最后一个承诺是 .finally() 返回的承诺)。每次您登录 a 时,您都在记录最终的承诺,并且在链完成之前尚未解决。

请记住,所有这些.then().finally() 方法都会立即执行并且每个都返回一个新的承诺。当它们执行时,它们会以一种方式注册传递给它们的回调,以便稍后在它们关联的 Promise 解析或拒绝时调用这些回调。即使第一个承诺立即解决,它仍然不会执行它的.then() 处理程序,直到整个.then().then().finally() 链执行并且该链中的所有承诺都被创建并且该链中指定的所有处理程序都被注册。因此,a 包含.finally() 返回的第四个承诺,而不是Promise.resolve() 创建的承诺,并且在您的链中的所有处理程序完成执行之前,第四个承诺不会被解决。由于您正在从所有这些处理程序进行日志记录,这就是为什么链中的最后一个承诺在您记录它的任何地方仍然显示为 pending

如果你这样做不同:

let d = Promise.resolve("123");

d.then(val => 
    console.log(d);
    return 100;
).then(val => 
    console.log(val);
    console.log(d);
).finally(() => 
    console.log(d);
);

然后,你会看到:

Promise  '123' 
100
Promise  '123' 
Promise  '123' 

因为现在d 代表链中的第一个promise,而不是链中的最后一个promise,所以当所有其他处理程序执行时它确实被解决了。

因此,您可能不知道这里的操作部分是每个.then().catch().finally() 返回一个新的承诺,该承诺与前面的链挂钩。您原来的 console.log(a) 仅监控链中的最后一个承诺,而不是链中的第一个承诺或链中的当前承诺。

【讨论】:

以上是关于为啥一个已解决的承诺仍处于待处理状态?的主要内容,如果未能解决你的问题,请参考以下文章

承诺仍在 then 块中待处理 - 如何解决? [复制]

PayPal webhook 所有事件仍处于待处理状态

Paypal Express Checkout 付款仍处于待处理状态,然后到期。确认返回 PENDINGREASON=order。

为啥 Amazon Sandbox 订单始终处于待处理状态?

HTTP OPTIONS 飞行前请求加载已取消,Chrome 中处于待处理状态

Python36 Discord Bot:任务已被破坏,但处于待处理状态