为什么我的承诺之后调用的函数在promise的回调之前执行?
我在MDN中读到了这个,但是没有理解它
"在完成当前之前永远不会调用回调 运行JavaScript事件循环。"
我认为这意味着如果我在resolve()
或reject()
之后有任何其他语句,它们将在调用回调之前执行。虽然,这似乎是一个不完整的理解。
function myFunction() {
return new Promise( function(resolve, reject) {
const err = false;
if(err) {
reject("Something went wrong!!!");
}
else {
resolve("All good");
}
});
}
myFunction().then(doSuccess).catch(doError);
doOther();
function doError(err) {
console.log(err);
}
function doSuccess() {
console.log('Success');
}
function doOther() {
console.log("My Other Function");
}
输出:
我的其他功能
成功
答案 0 :(得分:1)
根据规范,promise .then()
或.catch()
回调永远不会被同步调用,但会在事件循环的未来滴答中调用。这意味着您的同步代码的其余部分始终在调用任何.then()
处理程序之前运行。
因此,doOther()
函数会在调用doSuccess()
或doError()
之前运行。
Promise以这种方式设计,因此无论承诺是立即解决还是将来某个时间解决,都会以一致的时间调用promise .then()
处理程序。如果允许同步.then()
处理程序,那么调用代码要么必须知道它何时可以被同步调用,要么你很容易受到奇怪的定时错误的影响。
在ES6规范中的承诺所基于的Promises/A+ specification中,它定义了一个`.then()处理程序,如下所示:
promise.then(onFulfilled, onRejected)
然后对此进行说明:
2.2.4。在执行上下文堆栈仅包含平台代码之前,不得调用onFulfilled或onRejected。 [3.1]。
然后,它定义了这样的平台代码:
此处“平台代码”表示引擎,环境和承诺实现代码。实际上,这个要求确保onFulfilled和onRejected异步执行,然后调用事件循环,然后调用新堆栈。这可以使用诸如setTimeout或setImmediate之类的“宏任务”机制,或者使用诸如MutationObserver或process.nextTick之类的“微任务”机制来实现。由于promise实现被认为是平台代码,它本身可能包含一个任务调度队列或“trampoline”,其中调用处理程序。
基本上这意味着.then()
处理程序是通过在事件循环中插入一个任务来调用的,该任务在当前运行的Javascript完成之前不会执行,并将控制权返回给解释器(它可以检索下一个事件) )。因此,安装.then()
处理程序后,您拥有的任何同步Javascript代码将始终在调用.then()
处理程序之前运行。