Wkrótce kolejność zostanie zachowana .
Zgodnie ze specyfikacją, z którą się łączysz, Promise.all(iterable)
przyjmuje parametr iterable
(to znaczy obiekt obsługujący Iterator
interfejs) jako parametr, a następnie wywołuje PerformPromiseAll( iterator, constructor, resultCapability)
z nim wywołania , przy czym ten drugi iterable
używa pętli IteratorStep(iterator)
.
Oznacza to, że jeśli jeśli iterowalność, którą przekazujesz, Promise.all()
jest ściśle uporządkowana, to nadal zostanie zamówiona po przekazaniu.
Rozwiązanie jest realizowane za pośrednictwem miejsca, w Promise.all() Resolve
którym każda rozwiązana obietnica ma wewnętrzne [[Index]]
gniazdo, które oznacza indeks obietnicy na oryginalnym wejściu.
Wszystko to oznacza, że dane wyjściowe są ściśle uporządkowane jako dane wejściowe, o ile dane wejściowe są ściśle uporządkowane (na przykład tablica).
Możesz to zobaczyć w akcji w poniższym skrzypcach (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));
});
throw
wyjątkowy, jeśli prześlesz iterowalny doPromise.all
. Ponadto nie znam żadnych implementacji obietnic użytkowników, które obecnie wspierają przekazywanie iteracji, chociaż wielu debatowało nad tym i nie zdecydowało się na to.Promise.all
nie można użyć do uruchomienia szeregu obietnic w kolejności, jedna po drugiej. Obietnice załadowane do iteratora muszą być od siebie niezależne, aby działało przewidywalnie.Jak już wspomniano w poprzednich odpowiedziach,
Promise.all
agreguje wszystkie rozstrzygnięte wartości za pomocą tablicy odpowiadającej kolejności wprowadzania oryginalnych obietnic (patrz Agregowanie obietnic ).Chciałbym jednak zaznaczyć, że zamówienie jest zachowywane tylko po stronie klienta!
Dla programisty wygląda na to, że obietnice zostały spełnione w kolejności, ale w rzeczywistości obietnice są przetwarzane z różnymi prędkościami. Jest to ważne, aby wiedzieć, kiedy pracujesz ze zdalnym backendem, ponieważ backend może otrzymywać Twoje obietnice w innej kolejności.
Oto przykład, który pokazuje problem przy użyciu limitów czasu:
Promise.all
W powyższym kodzie podane są trzy obietnice (A, B, C)
Promise.all
. Trzy obietnice wykonują się przy różnych prędkościach (C jest najszybszy, a B jest najwolniejszy). Dlategoconsole.log
oświadczenia Obietnic pojawiają się w następującej kolejności:Jeśli obietnice są wywołaniami AJAX, zdalny backend otrzyma te wartości w tej kolejności. Ale po stronie klienta
Promise.all
zapewnia, że wyniki są uporządkowane zgodnie z pierwotnymi pozycjamimyPromises
tablicy. Właśnie dlatego końcowy wynik to:Jeśli chcesz zagwarantować również faktyczne wykonanie Twoich obietnic, potrzebujesz koncepcji takiej jak kolejka Obietnic. Oto przykład użycia kolejki p (uważaj, musisz zawinąć wszystkie obietnice w funkcje):
Sekwencyjna kolejka obietnic
Wynik
źródło
Tak, wartości w
results
są w tej samej kolejności copromises
.Można zacytować specyfikację ES6
Promise.all
, choć jest nieco skomplikowana ze względu na zastosowany interfejs iteratora i ogólny konstruktor obietnic. Jednak zauważysz, że każde wywołanie zwrotne resolvera ma[[index]]
atrybut, który jest tworzony w iteracji tablicy obietnic i używany do ustawiania wartości w tablicy wyników.źródło