Array.fromAsync()
Baseline
Weitgehend verfügbar
Diese Funktion ist gut etabliert und funktioniert auf vielen Geräten und in vielen Browserversionen. Sie ist seit Januar 2024 browserübergreifend verfügbar.
Die statische Methode Array.fromAsync() erstellt eine neue, flach kopierte Array-Instanz aus einem asynchronen Iterable, einem Iterable oder einem array-ähnlichen Objekt.
Syntax
Array.fromAsync(items)
Array.fromAsync(items, mapFn)
Array.fromAsync(items, mapFn, thisArg)
Parameter
items-
Ein asynchrones Iterable, Iterable oder array-ähnliches Objekt, das in ein Array konvertiert werden soll.
mapFnOptional-
Eine Funktion, die auf jedes Element des Arrays angewendet wird. Wenn bereitgestellt, wird jeder Wert, der dem Array hinzugefügt werden soll, zuerst durch diese Funktion geleitet, und der Rückgabewert von
mapFnwird stattdessen dem Array hinzugefügt (nachdem er awaited wurde). Die Funktion wird mit den folgenden Argumenten aufgerufen:element-
Das aktuelle Element, das im Array verarbeitet wird. Wenn
itemsein synchrones Iterable oder array-ähnliches Objekt ist, werden alle Elemente zuerst awaited, undelementwird nie ein thenable sein. Wennitemsein asynchrones Iterable ist, wird jeder erzeugte Wert unverändert übergeben. index-
Der Index des aktuellen Elements, das im Array verarbeitet wird.
thisArgOptional-
Wert, der als
thisbeim Ausführen vonmapFnverwendet werden soll.
Rückgabewert
Ein neues Promise, dessen Erfüllungswert eine neue Array-Instanz ist.
Beschreibung
Array.fromAsync() ermöglicht es, Arrays zu erstellen aus:
- asynchronen Iterable-Objekten (Objekte wie
ReadableStreamundAsyncGenerator); oder, wenn das Objekt nicht asynchron iterierbar ist, - iterierbaren Objekten (Objekte wie
MapundSet); oder, wenn das Objekt nicht iterierbar ist, - array-ähnlichen Objekten (Objekte mit einer
length-Eigenschaft und indizierten Elementen).
Array.fromAsync() iteriert das asynchrone Iterable auf eine Art und Weise, die sehr ähnlich zu for await...of ist. Array.fromAsync(items) ist im Allgemeinen äquivalent zu folgendem Code, wenn items ein asynchrones Iterable oder synchrones Iterable ist:
const result = [];
for await (const element of items) {
result.push(element);
}
Array.fromAsync() ist in Bezug auf das Verhalten fast gleichwertig mit Array.from(), außer den folgenden Unterschieden:
Array.fromAsync()verarbeitet asynchrone Iterable-Objekte.Array.fromAsync()gibt einPromisezurück, das sich zum Array-Instanz erfüllt.- Wenn
Array.fromAsync()mit einem nicht-asynchronen Iterable-Objekt aufgerufen wird, wird jedes Element, das zum Array hinzugefügt werden soll, zuerst awaited. - Wenn ein
mapFnbereitgestellt wird, wird dessen Ausgabe ebenfalls intern awaited.
Array.fromAsync() und Promise.all() können beide ein Iterable von Promises in ein Promise eines Arrays umwandeln. Es gibt jedoch zwei wesentliche Unterschiede:
Array.fromAsync()wartet auf jeden Wert, der aus dem Objekt erzeugt wird, nacheinander.Promise.all()wartet auf alle Werte gleichzeitig.Array.fromAsync()iteriert das Iterable träge und holt nicht den nächsten Wert, bevor der aktuelle geklärt ist.Promise.all()holt alle Werte im Voraus und wartet auf sie alle.
Beispiele
>Array aus einem asynchronen Iterable
const asyncIterable = (async function* () {
for (let i = 0; i < 5; i++) {
await new Promise((resolve) => setTimeout(resolve, 10 * i));
yield i;
}
})();
Array.fromAsync(asyncIterable).then((array) => console.log(array));
// [0, 1, 2, 3, 4]
Wenn items ein asynchrones Iterable ist, bei dem jeder Ergebniswert auch ein Promise ist, werden diese Promises ohne Awaiting dem resultierenden Array hinzugefügt. Dies ist konsistent mit dem Verhalten von for await...of.
function createAsyncIter() {
let i = 0;
return {
[Symbol.asyncIterator]() {
return {
async next() {
if (i > 2) return { done: true };
i++;
return { value: Promise.resolve(i), done: false };
},
};
},
};
}
Array.fromAsync(createAsyncIter()).then((array) => console.log(array));
// (3) [Promise, Promise, Promise]
Hinweis:
In der Praxis werden Sie selten ein asynchrones Iterable finden, das Promises liefert, da, wenn Sie es mit einer asynchronen Generatorfunktion implementieren, der yield-Ausdruck automatisch Promises entpackt.
Array aus einem synchronen Iterable
Array.fromAsync(
new Map([
[1, 2],
[3, 4],
]),
).then((array) => console.log(array));
// [[1, 2], [3, 4]]
Array aus einem synchronen Iterable, das Promises liefert
Array.fromAsync(
new Set([Promise.resolve(1), Promise.resolve(2), Promise.resolve(3)]),
).then((array) => console.log(array));
// [1, 2, 3]
Array aus einem array-ähnlichen Objekt von Promises
Array.fromAsync({
length: 3,
0: Promise.resolve(1),
1: Promise.resolve(2),
2: Promise.resolve(3),
}).then((array) => console.log(array));
// [1, 2, 3]
Verwendung von mapFn mit einem synchronen Iterable
Wenn items ein synchrones Iterable oder array-ähnliches Objekt ist, werden sowohl der Eingang als auch die Ausgabe von mapFn intern von Array.fromAsync() awaited.
function delayedValue(v) {
return new Promise((resolve) => setTimeout(() => resolve(v), 100));
}
Array.fromAsync(
[delayedValue(1), delayedValue(2), delayedValue(3)],
(element) => delayedValue(element * 2),
).then((array) => console.log(array));
// [2, 4, 6]
Verwendung von mapFn mit einem asynchronen Iterable
Wenn items ein asynchrones Iterable ist, wird der Eingang zu mapFn nicht awaited, die Ausgabe jedoch schon. Unter Verwendung der gleichen Funktion createAsyncIter wie oben:
Array.fromAsync(createAsyncIter(), async (element) => (await element) * 2).then(
(array) => console.log(array),
);
// [2, 4, 6]
Interessanterweise bedeutet dies, dass Array.fromAsync(createAsyncIter()) nicht äquivalent zu Array.fromAsync(createAsyncIter(), (element) => element) ist, da letzteres jeden erzeugten Wert awaited, während ersteres dies nicht tut.
Array.fromAsync(createAsyncIter(), (element) => element).then((array) =>
console.log(array),
);
// [1, 2, 3]
Vergleich mit Promise.all()
Array.fromAsync() wartet auf jeden Wert, der aus dem Objekt erzeugt wird, nacheinander. Promise.all() wartet auf alle Werte gleichzeitig.
function* makeIterableOfPromises() {
for (let i = 0; i < 5; i++) {
yield new Promise((resolve) => setTimeout(resolve, 100));
}
}
(async () => {
console.time("Array.fromAsync() time");
await Array.fromAsync(makeIterableOfPromises());
console.timeEnd("Array.fromAsync() time");
// Array.fromAsync() time: 503.610ms
console.time("Promise.all() time");
await Promise.all(makeIterableOfPromises());
console.timeEnd("Promise.all() time");
// Promise.all() time: 101.728ms
})();
Schluss von synchronen Iterables bei Ablehnung
Ähnlich wie bei for await...of, wenn das Objekt, das iteriert wird, ein synchrones Iterable ist und ein erzeugtes Promise abgelehnt wird, wird die Methode return() des zugrunde liegenden Iterators aufgerufen, falls vorhanden, um dem Iterator zu ermöglichen, Bereinigungen vorzunehmen.
function* generatorWithRejectedPromises() {
try {
yield 0;
yield Promise.reject(new Error("error"));
} finally {
console.log("called finally");
}
}
(async () => {
try {
await Array.fromAsync(generatorWithRejectedPromises());
} catch (e) {
console.log("caught", e);
}
})();
// called finally
// caught Error: error
Spezifikationen
| Spezifikation |
|---|
| ECMAScript® 2027 Language Specification> # sec-array.fromasync> |