【问题标题】:In Javascript, why evaluating a `then` method on a "resolved" Promise returns a "pending" Promise?在 Javascript 中,为什么在“已解决”的 Promise 上评估“then”方法会返回“待处理”的 Promise?
【发布时间】:2016-04-05 08:06:34
【问题描述】:

以下是原生 Javascript 代码:

var first = Promise.resolve(1);
first.then((i)=>console.log(1))

当我在 Chrome 的控制台中检查 first 时,它显示其状态为“已解决”

> first
Promise {[[PromiseStatus]]: "resolved", [[PromiseValue]]: 1}

但是,当我在 Chrome 的控制台中检查 first.then((i)=>console.log(1)) 时,它显示它的状态是“待定”

> first.then((i)=>console.log(1))
1
Promise {[[PromiseStatus]]: "pending", [[PromiseValue]]: undefined}

这让我感到困惑,因为我预计 first.then((i)=>console.log(1)) 的状态为 resolved,因为 then 方法中的回调已经执行并完成。

有人对此有想法吗?

【问题讨论】:

    标签: javascript asynchronous promise ecmascript-6


    【解决方案1】:

    Promise.resolve().then(fn) 返回一个尚未解决的新承诺,但将在当前执行线程展开并完成后的下一个滴答声中解决。

    因此,如果您立即检查返回的 Promise 是否已解决,则不会。但是,如果你等到下一个滴答声,它就会被解决,届时将触发 .then() 处理函数。

    解释一下,对.then() 的每个链接调用都会返回一个新的承诺,该承诺链接到前一个承诺。而且,根据 Promise A+ 规范,所有.then() 回调处理程序在堆栈展开后异步触发(从技术上讲,它表示“只有平台代码在堆栈上”)。

    所以,.then() 立即同步运行。它将您传递给它的回调存储在 Promise 对象中,然后这些回调实际上在将来的某个时间被异步调用。如果 Promise 被快速解决,那么当当前执行线程完成时,将在下一个“tick”调用完成回调。

    此堆栈展开并在下一个滴答时触发是为了使.then() 处理程序始终异步触发,无论承诺解决的速度有多快。这允许在立即解决承诺时以一致的方式编写调用代码,在 1 毫秒或 20 分钟内。它们都将在未来某个时间异步解决,因此调用代码可以对它们一视同仁。唯一不同的是从现在开始解决或拒绝的时间。

    【讨论】:

      【解决方案2】:

      对于确认到Promise/A+ spec 的承诺,对于表单的then 调用

      promise.then(onFulfilled, onRejected)
      

      有一个条件

      在执行上下文堆栈仅包含平台代码之前,不得调用 onFulfilled 或 onRejected。

      因此,假设 Chrome 遵守此规范的承诺,并且仅在调用回调后将(内部?)承诺状态设置为 resolved,调用

      Promise.resolve(1).then(onFulfilled, onRejected);
      

      将始终显示未解决的承诺,因为堆栈尚未清除且尚未调用回调。然而,

      var derived = Promise.resolve(1).then(onFulfilled, onRejected);
      

      然后,在检查员调用中

      derived;
      

      将显示一个已解决的承诺,因为堆栈已清除并调用了回调。对

      的调用
      Promise.resolve(1);
      

      不受必须等待堆栈清除的约束,因此返回一个立即解决的承诺。

      【讨论】:

        猜你喜欢
        • 2020-04-16
        • 2018-09-25
        • 1970-01-01
        • 2016-12-28
        • 2019-05-28
        • 1970-01-01
        • 1970-01-01
        • 2017-10-24
        • 1970-01-01
        相关资源
        最近更新 更多