Рассматривая MDN, он выглядит как values
, переданный обратному сообщению then()
для Promise.all, содержит значения порядка promises. Например:
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: Выполнение такого кода показало, что это кажется правдой, хотя это, конечно, не доказательство - это могло быть совпадением.
Ответ 1
Вскоре порядок сохраняется.
Следуя спецификации, с которой вы связаны, Promise.all(iterable)
принимает iterable
(то есть объект, который поддерживает Iterator
interface) как параметр, а затем - вызовы PerformPromiseAll (итератор, конструктор, resultCapability)
с ним, где последний перебирает итеративный
с помощью IteratorStep (iterator)код>
.
Это означает, что если, если итерабельность, которую вы передаете в Promise.all()
, строго упорядочена, они все равно будут упорядочены после прохождения.
Разрешение выполняется через Promise.all() Resolve
, где каждое разрешенное обещание имеет внутренний слот [[Index]]
, который отмечает индекс обещания в исходном входе.
Все это означает, что вывод строго упорядочен как вход, если вход строго упорядочен (например, массив).
Вы можете увидеть это в действии в приведенном ниже скрипте (ES6):
//Используется для отображения результатов
const write = msg = > {
document.body.appendChild(document.createElement('div')). innerHTML = msg;
};
// Различные операции с асинхронной скоростью
const slow = new Promise (resolve = > {
setTimeout (разрешение, 200, "медленный" );
});
const instant = 'instant';
const quick = new Promise (resolve = > {
setTimeout (разрешить, 50, "быстро" );
});
// Порядок сохраняется независимо от того, что разрешено первым
Promise.all([медленный, мгновенный, быстрый]), затем (response = > {
response.map(response = > write (response));
});Код>
Ответ 2
Да, значения в results
находятся в том же порядке, что и promises
.
Можно было бы указать спецификацию ES6 на Promise.all
, хотя она немного запутана из-за использованного итератора api и универсального конструктора обещаний. Тем не менее, вы заметите, что каждый обратный вызов resolver имеет атрибут [[index]]
, который создается в итерации с обещанием и используется для установки значений в массиве результатов.
Ответ 3
Как уже отмечалось в предыдущих ответах, Promise.all
объединяет все разрешенные значения с массивом, соответствующим порядку ввода исходных обещаний (см. Агрегирование обещаний).
Однако я хотел бы указать, что заказ сохраняется только на стороне клиента!
Разработчику кажется, что обещания были выполнены в порядке, но на самом деле обещания обрабатываются с разной скоростью. Это важно знать, когда вы работаете с удаленным бэкэнд, потому что бэкэнд может получать ваши обещания в другом порядке.
Вот пример, демонстрирующий проблему с помощью тайм-аутов:
Promise.all
const myPromises = [
new Promise ((разрешить) = > setTimeout (() = > {разрешить ( "A (медленный)" ); console.log( "A (медленный)" )}, 1000)),
new (Promise) ((разрешить) = > setTimeout (() = > {разрешить ('B (медленнее)'); console.log('B (медленнее)')}, 2000)),
new Promise ((разрешить) = > setTimeout (() = > {resolve ('C (fast)'); console.log('C (fast)')}, 10))
];
Promise.all(myPromises).then(console.log)код>