以下是原生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
方法中的回调已经执行并完成。
有没有人有这方面的想法?
答案 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);
不受必须等待堆栈清除的限制,因此返回一个立即解决的承诺。