Start · Sprachen · JavaScript · Referenz · ReadableStreamBYOBReader.read()

ReadableStreamBYOBReader.read()

Methode

Liest Bytes aus einem lesbaren Bytestrom direkt in eine selbst bereitgestellte Pufferansicht (<code>TypedArray</code>/<code>DataView</code>) und liefert ein Promise mit <code>{ value, done }</code>.

seit JavaScript Baseline 2024 (Chrome 89+, Firefox 102+, Safari 18 Kategorie: webapi

Signatur

ReadableStreamBYOBReader.prototype.read(view, options)

Beschreibung

Die Methode read() eines ReadableStreamBYOBReader („Bring Your Own Buffer“) liest Daten aus einem Bytestrom (new ReadableStream({ type: "bytes" }), z. B. auch Response.body) direkt in einen Speicherbereich, den du vorgibst. Dadurch lassen sich Kopien und ständige Neuallokationen vermeiden – ideal für Binärprotokolle, große Downloads, Dateiparser oder speicherkritische Anwendungen, in denen ein Puffer immer wieder verwendet werden soll.

Beim Aufruf wird der zugrunde liegende ArrayBuffer der übergebenen Ansicht übertragen (transferiert): Die ursprüngliche Ansicht ist danach abgekoppelt (byteLength === 0) und darf nicht mehr verwendet werden. Das aufgelöste Ergebnis enthält in value eine neue Ansicht desselben Typs über denselben Speicher, deren Länge der Zahl tatsächlich gelesener Elemente entspricht. Für den nächsten Lesevorgang verwendet man value.buffer weiter.

Das Promise wird aufgelöst, sobald Daten vorliegen – es können also weniger Bytes geliefert werden, als die Ansicht fasst. Mit der Option min lässt sich erzwingen, dass mindestens eine bestimmte Anzahl Elemente gelesen wird (außer der Strom endet vorher). Ist der Strom geschlossen, gilt done: true und value ist eine leere Ansicht über den zurückgegebenen Puffer; wurde er abgebrochen, ist value undefined.

Parameter

Name Typ Default Beschreibung
$view Pflicht TypedArray | DataView Ansicht auf den Zielpuffer, in den die Bytes geschrieben werden. Muss eine byteLength > 0 haben und darf nicht abgekoppelt sein. Der Puffer wird bei Aufruf transferiert.
$options { min?: number } {} Optionales Objekt. min: Mindestanzahl an Elementen (nicht Bytes, außer bei Uint8Array/DataView), die gelesen werden sollen, bevor das Promise erfüllt wird. Standard ist 1; darf die Länge der Ansicht nicht überschreiten.

Rückgabewert

Typ
Promise<{ value: TypedArray | DataView | undefined, done: boolean }>
Beschreibung
Promise mit einem Ergebnisobjekt: value ist eine neue Ansicht (gleicher Typ wie view) auf die gelesenen Daten, done gibt an, ob der Strom beendet ist. Wird mit TypeError abgelehnt bei ungültiger Ansicht, freigegebenem Reader oder ungültigem min; bei einem fehlerhaften Strom mit dessen Fehler.

Beispiele

Bytestrom mit wiederverwendetem Puffer lesen

const stream = new ReadableStream({
  type: "bytes",
  start(controller) {
    controller.enqueue(new Uint8Array([1, 2, 3, 4, 5]));
    controller.close();
  }
});

const reader = stream.getReader({ mode: "byob" });
let buffer = new ArrayBuffer(4);

while (true) {
  const { value, done } = await reader.read(new Uint8Array(buffer));
  if (done) break;
  console.log(Array.from(value));
  // Puffer wurde transferiert – den zurückgegebenen weiterverwenden
  buffer = value.buffer;
}
console.log("Fertig");
[1, 2, 3, 4] [5] Fertig

Download-Größe mit festem 64-KiB-Puffer zählen

const countBytes = async (url) => {
  const response = await fetch(url);
  const reader = response.body.getReader({ mode: "byob" });
  let buffer = new ArrayBuffer(64 * 1024);
  let total = 0;

  try {
    while (true) {
      const { value, done } = await reader.read(new Uint8Array(buffer));
      if (done) break;
      total += value.byteLength;
      buffer = value.buffer;
    }
  } finally {
    reader.releaseLock();
  }
  return total;
};

console.log(await countBytes("/daten.bin"), "Bytes");
z. B. 1048576 Bytes

Festen Binär-Header mit der Option min lesen

const readHeader = async (stream) => {
  const reader = stream.getReader({ mode: "byob" });
  // Erst erfüllen, wenn alle 8 Header-Bytes da sind
  const { value, done } = await reader.read(new Uint8Array(8), { min: 8 });
  reader.releaseLock();
  if (done || value.byteLength < 8) throw new Error("Header unvollständig");

  const view = new DataView(value.buffer, value.byteOffset, value.byteLength);
  return { magic: view.getUint32(0), length: view.getUint32(4) };
};

const stream = new ReadableStream({
  type: "bytes",
  start(c) {
    c.enqueue(new Uint8Array([0xCA, 0xFE, 0xBA, 0xBE]));
    c.enqueue(new Uint8Array([0, 0, 1, 0]));
    c.close();
  }
});
console.log(await readHeader(stream));
{ magic: 3405691582, length: 256 }

// Wichtig · Fallstricke

  • Abgekoppelter Puffer: Nach read(view) ist view unbrauchbar (byteLength 0). Immer mit value bzw. value.buffer weiterarbeiten – ein erneuter Aufruf mit der alten Ansicht führt zu einem TypeError.
  • Teil-Lesevorgänge: Ohne min kann value kürzer sein als die Ansicht. Nie davon ausgehen, dass der Puffer vollständig gefüllt wurde.
  • min zählt Elemente der Ansicht, nicht Bytes (bei Uint32Array also 4-Byte-Einheiten). Die Option ist neuer als die Methode selbst – ältere Browser ignorieren sie stillschweigend; Unterstützung vorher prüfen.
  • Funktioniert nur mit Bytströmen (type: "bytes"). getReader({ mode: "byob" }) auf einem normalen Strom wirft einen TypeError. Response.body ist in aktuellen Browsern ein Bytestrom, in Safari erst ab 18.4 BYOB-fähig.
  • Eine SharedArrayBuffer-basierte Ansicht ist nicht zulässig, da sie nicht transferiert werden kann.
  • Nach Abschluss releaseLock() aufrufen, damit andere Konsumenten den Strom nutzen können.