Обещать.все: Порядок разрешенных значений
смотрим MDN похоже values перешло к then() обратный вызов обещания.все содержит значения в порядке обещаний. Например:
var somePromises = [1, 2, 3, 4, 5].map(Promise.resolve);
return Promise.all(somePromises).then(function(results) {
console.log(results) // is [1, 2, 3, 4, 5] the guaranteed result?
});
может ли кто-нибудь процитировать спецификацию, указав, в каком порядке values должно быть?
PS: запуск такого кода показал, что это похоже на правду, хотя это, конечно, не доказательство - это могло быть совпадением.
3 ответов:
в ближайшее время порядок сохраняется.
следуя спецификации, которую вы связали,
Promise.all(iterable)принимаетiterable(то есть, объект, который поддерживаетIteratorинтерфейс) в качестве параметра и позже на звонкиPerformPromiseAll( iterator, constructor, resultCapability)с ним, где последний петли надiterableиспользуяIteratorStep(iterator).
Это означает, что если если iterable вы передаете вPromise.all()строго приказано, они все еще будут приказаны раз прошел внутрь.разрешение осуществляется через
Promise.all() Resolveгде каждое разрешенное обещание имеет внутренний[[Index]]слот, который отмечает индекс обещания в исходном входе.
все это означает, что выход строго упорядочен как вход до тех пор, пока вход строго упорядочен (например, массив).
вы можете увидеть это в действии в приведенной ниже скрипке (ES6):
// Used to display results const write = msg => { document.body.appendChild(document.createElement('div')).innerHTML = msg; }; // Different speed async operations const slow = new Promise(resolve => { setTimeout(resolve, 200, 'slow'); }); const instant = 'instant'; const quick = new Promise(resolve => { setTimeout(resolve, 50, 'quick'); }); // The order is preserved regardless of what resolved first Promise.all([slow, instant, quick]).then(responses => { responses.map(response => write(response)); });
да, значения в
resultsнаходятся в том же порядке, что иpromises.можно было бы процитировать ES6 spec on
Promise.all, хотя это немного запутано из-за используемого api итератора и универсального конструктора обещаний. Однако вы заметите, что каждый обратный вызов решателя имеет[[index]]атрибут, который создается в итерации promise-array и используется для установки значений в результирующем массиве.
как уже говорилось в предыдущих ответах,
Promise.allагрегирует все разрешенные значения с массивом, соответствующим порядку ввода исходных обещаний (см. Агрегация Обещания).однако, я хотел бы отметить, что порядок сохраняется только на стороне клиента!
разработчику кажется, что обещания были выполнены по порядку, но на самом деле обещания обрабатываются с разной скоростью. Это важно знайте, когда вы работаете с удаленным бэкэндом, потому что бэкэнд может получать ваши обещания в другом порядке.
вот пример, который демонстрирует проблему с помощью тайм-аутов:
обещание.все
const myPromises = [ new Promise((resolve) => setTimeout(() => {resolve('A (slow)'); console.log('A (slow)')}, 1000)), new Promise((resolve) => setTimeout(() => {resolve('B (slower)'); console.log('B (slower)')}, 2000)), new Promise((resolve) => setTimeout(() => {resolve('C (fast)'); console.log('C (fast)')}, 10)) ]; Promise.all(myPromises).then(console.log)в коде, показанном выше, три обещания (A, B, C) даны
Promise.all. Три обещания выполняются с разной скоростью (C-самый быстрый, А B-самый медленный). Вот почемуconsole.logзаявления об обещаниях отображаются в следующем порядке:C (fast) A (slow) B (slower)если обещания являются вызовами AJAX, то удаленный сервер получит эти значения в следующем порядке. Но на стороне клиента
Promise.allгарантирует, что результаты упорядочены в соответствии с исходными позициямиmyPromisesмассив. Вот почему окончательный результат:['A (slow)', 'B (slower)', 'C (fast)']если вы хотите гарантировать также фактическое выполнение Ваших обещаний, то вам понадобится концепция, такая как очередь обещаний. Вот пример использования п-очереди (будьте осторожны, вам нужно обернуть все обещания в функции):
Последовательная Очередь Обещаний
const PQueue = require('p-queue'); const queue = new PQueue({concurrency: 1}); // Thunked Promises: const myPromises = [ () => new Promise((resolve) => setTimeout(() => { resolve('A (slow)'); console.log('A (slow)'); }, 1000)), () => new Promise((resolve) => setTimeout(() => { resolve('B (slower)'); console.log('B (slower)'); }, 2000)), () => new Promise((resolve) => setTimeout(() => { resolve('C (fast)'); console.log('C (fast)'); }, 10)) ]; queue.addAll(myPromises).then(console.log);результат
A (slow) B (slower) C (fast) ['A (slow)', 'B (slower)', 'C (fast)']
Comments