Start · Sprachen · JavaScript · Referenz · Array.fromAsync()

Array.fromAsync()

Methode

Erstellt asynchron ein neues, flach kopiertes Array aus einem asynchronen Iterable, einem Iterable oder einem array-ähnlichen Objekt und gibt ein <code>Promise</code> darauf zurück.

seit JavaScript Baseline 2024 (Chrome 121, Firefox 115, Safari 16. Kategorie: method-property

Signatur

Array.fromAsync(items, mapFn, thisArg)

Beschreibung

Array.fromAsync() ist das asynchrone Gegenstück zu Array.from(). Die Methode durchläuft ein asynchrones Iterable (z. B. einen async function*-Generator oder einen ReadableStream), ein normales Iterable oder ein array-ähnliches Objekt, wartet jeden Wert mit await ab und sammelt die Ergebnisse in einem neuen Array. Zurückgegeben wird ein Promise, das mit diesem Array erfüllt wird.

Im Kern ersetzt die Methode das übliche Muster const result = []; for await (const x of source) result.push(x); durch einen einzigen Ausdruck. Das ist besonders praktisch, wenn man z. B. Seiten einer paginierten API, Zeilen aus einem Stream oder Ergebnisse eines asynchronen Generators komplett einsammeln will.

Wichtig: Die Werte werden nacheinander verarbeitet, nicht gleichzeitig. Jeder Wert (und jedes Ergebnis von mapFn) wird abgewartet, bevor der nächste angefordert wird. Wer mehrere voneinander unabhängige Promises parallel auflösen will, ist mit Promise.all() meist besser bedient.

Ist items weder asynchron noch synchron iterierbar, wird es als array-ähnliches Objekt behandelt: Über die Indizes 0 bis length - 1 wird iteriert, und auch hier wird jeder Wert abgewartet.

Parameter

Name Typ Default Beschreibung
$items Pflicht AsyncIterable|Iterable|ArrayLike Die Quelle, aus der das Array erstellt wird. Vorrang hat [Symbol.asyncIterator], danach [Symbol.iterator], zuletzt length plus Indizes.
$mapFn (element: any, index: number) => any undefined Wird für jedes Element aufgerufen, nachdem es abgewartet wurde. Der Rückgabewert (auch ein Promise) wird ebenfalls abgewartet und landet im Ergebnis-Array. Anders als bei Array.prototype.map() erhält die Funktion nur element und index.
$thisArg any undefined Wert, der beim Aufruf von mapFn als this verwendet wird.

Rückgabewert

Typ
Promise<Array>
Beschreibung
Ein Promise, das mit dem neuen Array erfüllt wird. Es wird abgelehnt, wenn die Iteration, ein Element-Promise oder mapFn einen Fehler wirft bzw. ablehnt.

Beispiele

Asynchronen Generator in ein Array umwandeln

const sleep = (ms) => new Promise((r) => setTimeout(r, ms));

async function* zaehle(bis) {
  for (let i = 1; i <= bis; i++) {
    await sleep(50);
    yield i;
  }
}

const zahlen = await Array.fromAsync(zaehle(5));
console.log(zahlen);
[1, 2, 3, 4, 5]

Paginierte API komplett einsammeln

// Liefert alle Einträge einer paginierten REST-API seitenweise
async function* ladeAlleSeiten(url) {
  let naechste = url;
  while (naechste) {
    const res = await fetch(naechste);
    if (!res.ok) throw new Error(`HTTP ${res.status}`);
    const { items, next } = await res.json();
    yield* items;
    naechste = next; // null, wenn keine weitere Seite existiert
  }
}

try {
  const benutzer = await Array.fromAsync(
    ladeAlleSeiten('https://api.example.com/users?page=1'),
    (u) => u.name
  );
  console.log(`${benutzer.length} Benutzer geladen`);
} catch (err) {
  console.error('Laden fehlgeschlagen:', err.message);
}

Asynchrone mapFn mit Index

const ids = [101, 102, 103];

const ladeProdukt = async (id) => ({ id, preis: id * 1.5 });

// Das Promise aus mapFn wird automatisch abgewartet
const produkte = await Array.fromAsync(ids, async (id, index) => {
  const p = await ladeProdukt(id);
  return `${index + 1}. Produkt ${p.id}: ${p.preis} €`;
});

console.log(produkte);
['1. Produkt 101: 151.5 €', '2. Produkt 102: 153 €', '3. Produkt 103: 154.5 €']

Array-ähnliches Objekt mit Promises

const arrayLike = {
  length: 3,
  0: Promise.resolve('a'),
  1: 'b',
  2: new Promise((r) => setTimeout(() => r('c'), 100)),
};

const ergebnis = await Array.fromAsync(arrayLike);
console.log(ergebnis);
['a', 'b', 'c']

// Wichtig · Fallstricke

  • Nacheinander statt parallel: Array.fromAsync() wartet jedes Element einzeln ab. Bei einem Array bereits gestarteter Promises ist das Ergebnis zwar gleich, aber bei asynchroner mapFn laufen die Aufrufe hintereinander. Für echte Parallelität Promise.all(items.map(fn)) verwenden.
  • Unbehandelte Ablehnungen: Übergibt man ein synchrones Iterable von Promises und lehnt eines davon ab, bricht Array.fromAsync() ab. Später ablehnende Promises werden dann nicht mehr beobachtet und können als unhandledrejection auftauchen. Promise.all() bzw. Promise.allSettled() verhalten sich hier robuster.
  • Kein Ersatz für unendliche Quellen: Bei endlosen asynchronen Iterables (z. B. Event-Streams ohne Ende) wird das Promise nie erfüllt, der Speicher wächst unbegrenzt.
  • mapFn-Unterschied: Die Callback-Funktion erhält nur zwei Argumente (element, index), nicht das Quell-Array.
  • Generisch: Wie Array.from() kann die Methode über call mit einem anderen Konstruktor als this aufgerufen werden, der dann das Ergebnisobjekt erzeugt.
  • Kompatibilität: Erst seit 2024 in allen großen Browsern verfügbar (Chrome/Edge 121, Firefox 115, Safari 16.4) sowie in Node.js ab Version 22 und Deno. Für ältere Umgebungen gibt es Polyfills (z. B. core-js) oder man nutzt eine for await...of-Schleife.
  • await auf oberster Ebene (Top-Level-Await) in den Beispielen funktioniert nur in ES-Modulen oder der Browser-Konsole.