Как предыдущих ответы уже говорились, Promise.all
агрегатов всех разрешенных значений с массивом, соответствующим порядок ввода первоначальных обещаний (см. Aggregating 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))
];
Promise.all(myPromises).then(console.log)
В коде показано выше, три Обещания (A, B, C), приведены в Promise.all
. Три Promises выполняются с разной скоростью (C является самым быстрым, а B - самым медленным). Вот почему console.log
высказывания обетований показывают в следующем порядке:
C (fast)
A (slow)
B (slower)
Если Обещания AJAX вызовов, то удаленный бэкенд получит эти значения в указанном порядке. Но на стороне клиента Promise.all
гарантирует, что результаты упорядочены в соответствии с исходными позициями массива myPromises
. Вот почему конечный результат:
['A (slow)', 'B (slower)', 'C (fast)']
Если вы хотите, чтобы гарантировать также фактическое исполнение своих обещаний, то вам нужно будет такое понятие, как очереди Promise. Ниже приведен пример использования p-queue (будьте осторожны, вам нужно обернуть все посылы в функции):
Последовательная Promise Очередь
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)']
Как можно было бы строго упорядочить итерацию? Любой итерабельный «строго упорядочен» по порядку, в котором он производит свои значения. –
Примечание. Firefox является единственным браузером, который правильно выполняет итерации в обещаниях. В настоящее время Chrome будет «бросать» excpetion, если вы передадите итерабельному «Promise.all». Кроме того, мне не известно о реализации пользовательских обещаний, которые в настоящее время поддерживают передачу итераций, хотя многие из них обсуждали это и решили против этого в то время. –
@BenjaminGruenbaum 'Object' не имеет поведения итерации по умолчанию (потому что он не строго упорядочен), что означает, что если вы используете его вместе с предоставлением ему итерационного интерфейса, порядок может быть неоднозначным в зависимости от реализации. – Nit