为什么我的函数在我的promise回调之前执行?

时间:2018-03-10 23:12:34

标签: javascript promise

为什么我的承诺之后调用的函数在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");
}

输出:

我的其他功能

成功

1 个答案:

答案 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()处理程序之前运行。