2016-03-19 3 views
3

Я запускаю образец кода ниже на моей машине (с установленным узлом 5.8.0) и получаю следующий результат (см. После примера кода).Почему Promise.all (массив) не разрешен немедленно?

Пример кода:

'use strict' 

var p1 = Promise.resolve(); 
var p2 = Promise.resolve(); 

var p12 = Promise.all([p1, p2]); 

var cb = function() { 
    console.log(p12); 
} 

setTimeout(cb, 0); 

console.log(p1); 
console.log(p2); 
console.log(p12); 

Результат:

Promise {неопределенная}
Promise {неопределенный}
Promise {<pending>}
Promise {[не определенно, не определенно]}

Почему это так, что p12 не разрешалось сразу после p1 и p2 (давая p1 и p1 в начале программы), и почему «timeouted» p12 был разрешен? Требуется ли некоторое время, необходимое для решения Promise.all (array)?

+0

Попытайтесь изменить свои разрешения на: 'Promise.resolve (true);' – CodingGorilla

ответ

4

В соответствии с техническим заданием обещание выполнить или отклонить обработчик всегда называют асинхронно ПОСЛЕ завершения цикла события. Таким образом, p12 не разрешается немедленно, даже если аргументы для него - все разрешенные обещания. Таким образом, он не будет устранен до тех пор, пока не закончится цикл этого события. Это объясняет, почему ваш первый отчет:

console.log(p12); 

показывает, что обещание по-прежнему «ожидает». Это текущие .then() обработчики (если они есть) еще не были вызваны. Однако, как только текущий поток кода завершит выполнение и управление вернется к следующему событию в очереди событий, обещание будет разрешено, и, таким образом, ваш setTimeout() видит, что он будет разрешен к тому времени.


Это делается по соображениям совместимости вызывающего абонента, так что .then() обработчиков не вызывается последовательно в асинхронном режиме, независимо от того, было ли обещание уже решены или пока не решено. Это позволяет коду вызова всегда кодировать последовательно, не беспокоясь о том, может ли обещание уже разрешиться. Во всех случаях вызывается обработчики .then() после того, как текущий стек разматывается и заканчивается.

Из Promises/A+ specification:

onFulfilled или onRejected не должен вызываться до выполнения контекста стек содержит только код платформы.

Здесь «код платформы» означает двигатель, окружающую среду и обещание код реализации. На практике это требование гарантирует, что onFulfilled и onRejected выполняются асинхронно, после того, как событие завершает цикл, в котором затем вызывается, и со свежей стекой. Это может быть , реализованный либо с помощью механизма макрозадачи, такого как setTimeout, либо setImmediate, или с помощью механизма «микрозадания», такого как MutationObserver или process.nextTick. Поскольку реализация обещания считается кодом платформы, она сама может содержать очередь планирования задач очереди или «трамплин», в которой вызываются обработчики.

Итак, результат всего этого заключается в том, Хотя внутренние детали могут быть немного сложнее, чем это (возможно, связанные с микро-задачами), вы можете логически подумать о том, что обещание будет устранено, отправив сообщение в очередь событий, которое теперь ожидает разрешения/отклонения. И всякий раз, когда очередь событий заканчивает то, что в настоящее время работает, и получает поворот для выполнения обещаний .then() обработчиков, только тогда они будут выполняться.

+0

Итак, «.all (array)» следует понимать аналогично обработчику «.then()» (а не методу «.resolve()») ... Имеет смысл. Благодарю. @ jfriend00 – olegzhermal

Смежные вопросы