2017-01-22 20 views
7

Я изучаю Promise, чтобы понять это. Я немного прочитал о цикле событий JavaScript. В этом article кратко представлена ​​работа цикла событий, такая как стек вызовов, таблица событий и очередь сообщений.Понимание порядка выполнения последующих обработчиков then() разрешенных обещаний

Но я не знаю, как стек вызовов имеет дело с линией, содержащей «возврат», и что происходит после этого. Ниже приведен пример, который я написал, чтобы надеяться понять, как работает 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 30;, 1.1.2, 1.1.3 после 15, но при использовании return new Promise(...), 1.1.2, 1.1.3 - до 15. Так что же произошло, когда код достиг двух разных «возвращений»?

+1

Удалены обратные вызовы из 1.1.4 и 1.1.5 - они не упоминаются и не могут быть понятны, и все уже доходят до 1.1.2. Каждый сможет по-прежнему понять эту дилемму без них. –

+0

@ try-catch-finally, Спасибо за ваше предложение и редактирование. Я просто хотел сделать это яснее, хотя иногда это делает обратное :) –

+0

Итак, @ try-catch - наконец-то, мне интересно, можете ли вы дать советы по моему вопросу? Спасибо –

ответ

2

Разница описана в http://promisesaplus.com/ в соответствии с процедурой разрешения обещания.

Для первого возвращаемого значения:

2.3.3.4 Если же это не функция, выполнить обещание с й.

Для второго:

2.3.2 Если х обещание, принимает свое состояние [3,4]:

2.3.2.2 Если/когда х выполнено, выполнить обещание с одинаковое значение.

Мы можем видеть, что это реализовано 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, у нас есть два отдельных объекта обещание: один возвращается из функции передается 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 
+0

Большое спасибо за вашу статью, в которой очень четко указано, что я хочу знать ! –