Обещать.все: Порядок разрешенных значений



смотрим 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: запуск такого кода показал, что это похоже на правду, хотя это, конечно, не доказательство - это могло быть совпадением.

405   3  

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

    Ничего не найдено.