在Javascript中,为什么要评估一个'then`方法来解决"承诺返回"待定"诺言?

时间:2016-04-05 08:06:35

标签: javascript asynchronous promise ecmascript-6

以下是原生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方法中的回调已经执行并完成。

有没有人有这方面的想法?

2 个答案:

答案 0 :(得分:5)

Promise.resolve().then(fn)返回一个尚未解决的新承诺,但会在当前执行线程展开并完成后的下一个刻度上解析。

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

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

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

这个堆栈在下一个tick上展开和触发是为了使.then()处理程序始终异步触发,而不管请求解决的速度有多快。这允许在1ms或20分钟内立即解决承诺时以一致的方式写入调用代码。它们将在未来的某个时间异步解析,因此调用代码可以对它们进行相同的处理。唯一不同的是,从现在开始,它们会被解决或拒绝多久。

答案 1 :(得分:0)

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

promise.then(onFulfilled, onRejected)

有条件

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

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

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

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

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

然后,在检查员调用

derived;

将显示已解决的承诺,因为堆栈已清除且调用了回调。致电

Promise.resolve(1);

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