了解已解决的promise

时间:2017-01-22 07:57:25

标签: javascript callstack event-loop

我正在学习Promise,为了理解它我读了一些关于JavaScript的事件循环。这个article简要地介绍了事件循环的工作,例如调用堆栈,事件表和消息队列。

但我不知道调用堆栈如何处理包含' return'以及之后发生的事情。 下面是我写的一个例子,希望了解Promise如何基于事件循环工作。如果您想试一试,请参阅http://jsbin.com/puqogulani/edit?js,console

var p1 = new Promise(
  function(resolve, reject){
    resolve(0);
});

p1.then(function(val){
  console.log(val);
  p1.then(function(){
    console.log("1.1.1");
    p1.then(function(){
      console.log("1.1.2");
      p1.then(function(){
        console.log("1.1.3");
      });
    });
  });

  p1.then(function(){
    console.log("1.2");
  })

  return 30;

  //return new Promise(function(resolve, reject){
  //  resolve(30);
  //});

})
  .then(function(val){
  console.log(val/2);
});

p1.then(function(){
  console.log("2.1");
});

console.log("Start");

可以看出,有两个" return",使用它们中的每个将给出不同的输出顺序。具体来说,使用return 30;时,1.1.2, 1.1.3位于15之后,但使用return new Promise(...)时,1.1.2, 1.1.3位于15之前。那么,当代码达到两个不同的“返回”时,究竟发生了什么?

1 个答案:

答案 0 :(得分:2)

差异在承诺解决程序的http://promisesaplus.com/中描述。

第一个返回值:

  

2.3.3.4如果那时不是一个函数,用x实现承诺。

第二个:

  

2.3.2如果x是一个承诺,则采用其状态[3.4]:

     

2.3.2.2如果/当x满足时,用相同的值履行承诺。

我们可以看到这已实施q.js。这是一种可能的实现,但似乎可以解释延迟:

function coerce(promise) {
    var deferred = defer();
    Q.nextTick(function () {
        try {
            promise.then(deferred.resolve, deferred.reject, deferred.notify);
        } catch (exception) {
            deferred.reject(exception);
        }
    });
    return deferred.promise;
}

当从then函数返回一个promise时,我们有两个单独的promise对象:从传递给then的函数返回的一个,以及从then返回的一个。这些需要连接在一起,以便解决第一个,解决第二个。这是通过promise.then(deferred.resolve, ...)

完成的

第一次延迟来自Q.nextTick。这将在事件循环的下一次迭代中执行该函数。在commit comments中讨论了为什么需要它。

调用promise.then会进一步延迟事件循环的一次迭代。根据规范的要求:

  

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

执行将类似于:

p1.then with function containing 1.1.1 is called
    function containing 1.1.1 is queued
p1.then with function containing 1.2 is called
    function containing 1.2 is queued
Promise resolving to 30 is returned
    Q.nextTick function is queued
----------
1.1.1 is printed
p1.then with function containing 1.1.2 is called
    function containing 1.1.2 is queued
1.2 is printed
Q.nextTick function is executed
    promise.then(deferred.resolve, ...) is queued
----------
1.1.2 is printed
p1.then with function containing 1.1.3 is called
    function containing 1.1.3 is queued
promise.then(deferred.resolve, ...) is executed
    function containing val/2 is queued
----------
1.1.3 is printed
val/2 is printed