2016-04-10 2 views
3

Я ожидаю, что выход для следующего фрагмента будет 1, 2, 3, 4. Но, фактический порядок вывода 1, 4, 3, 2.ES6 обещание выполнить заказ

self.promiseChain = new Promise(function (resolve, reject) { 
    setTimeout(resolve, 4000); 
}).then(function() { 
    console.log(1); 
}); 

self.promiseChain.then(function() { 
    return new Promise(function (resolve, reject) { 
    setTimeout(resolve, 3000); 
    }).then(function() { 
    console.log(2); 
    }); 
}); 

self.promiseChain.then(function() { 
    return new Promise(function (resolve, reject) { 
    setTimeout(resolve, 2000); 
    }).then(function() { 
    console.log(3); 
    }); 
}); 
self.promiseChain.then(function() { 
    return new Promise(function (resolve, reject) { 
    setTimeout(resolve, 200); 
    }).then(function() { 
    console.log(4); 
    }); 
}); 

http://www.es6fiddle.net/imu5bhoj/

Все, что я читал об обещаниях указывает, что это должно быть возможным, чтобы получить желаемый порядок в «плоской» цепи, как это. Видимо, мне не хватает деталей? Может ли кто-нибудь помочь указать мне в правильном направлении?

Вот скрипка (http://www.es6fiddle.net/imu6vh1o/), как это сделать не плоским способом, но сложнее рассуждать и делает неудобным последовательное соединение.

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

+1

Вы имели в виду 'self.promiseChain = self.promiseChain.then ...'? – elclanrs

+0

Yup @elclanrs, похоже, что это была моя проблема! –

ответ

8

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

Если вы хотите, чтобы эти четыре операции были упорядочены, вы должны на самом деле связать их друг с другом, а не все прикованные к одному и тому же обещанию. Помните, что .then() возвращает новое обещание, и это верное обещание, которое вы хотите связать, чтобы упорядочить вещи.

Вы делаете это:

var p = somePromise(); 

p.then(fn1); 
p.then(fn2); 
p.then(fn3); 

Это вызовет fn1, fn2 и fn3 в основном то же самое время и fn2 не будет ждать fn1 обещание разрешить.

Если вы хотите последовательности операций, то вы хотите, этот тип логики:

var p = somePromise(); 

p.then(fn1).then(fn2).then(fn3); 

Это не будет выполнять fn2 до fn1 обещание выполнено не будет и не будет выполнять fn3 пока fn2 обещание не будет сделано - таким образом, последовательность асинхронных операций.

Вот как это было бы, если бы они были фактически упорядочены один за другим.Вы действительно можете запустить этот фрагмент кода (но есть терпение, потому что он занимает 10 секунд для запуска):

var self = {}; 
 

 
self.promiseChain = new Promise(function (resolve, reject) { 
 
    setTimeout(resolve, 4000); 
 
}).then(function() { 
 
    log(1); 
 
}); 
 

 
var p = self.promiseChain.then(function() { 
 
    return new Promise(function (resolve, reject) { 
 
    setTimeout(resolve, 3000); 
 
    }).then(function() { 
 
    log(2); 
 
    }); 
 
}); 
 

 
p = p.then(function() { 
 
    return new Promise(function (resolve, reject) { 
 
    setTimeout(resolve, 2000); 
 
    }).then(function() { 
 
    log(3); 
 
    }); 
 
}); 
 
p = p.then(function() { 
 
    return new Promise(function (resolve, reject) { 
 
    setTimeout(resolve, 200); 
 
    }).then(function() { 
 
    log(4); 
 
    }); 
 
}); 
 

 
p.then(function() { 
 
    // last promise is done now 
 
    log("all done"); 
 
}); 
 

 
function log(x) { 
 
    var div = document.createElement("div"); 
 
    div.innerHTML = x; 
 
    document.body.appendChild(div); 
 
}

См эти другие подобные ответы:

Execute native js promise in series

Understanding javascript promises; stacks and chaining

Is there a difference between promise.then.then vs promise.then; promise.then

+0

Спасибо, @ jfriend00! Наверное, я могу понять вниз. Угадайте, я должен освежить свои навыки поиска в stackoverflow. Во всяком случае, мое непонимание сейчас кристально ясно, и я могу наконец поднять голову с клавиатуры! –

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