Start · Sprachen · JavaScript · Referenz · new ReadableStreamBYOBReader()

new ReadableStreamBYOBReader()

Methode

Erzeugt einen BYOB-Reader („bring your own buffer“), der Daten aus einem Byte-Stream direkt in einen von dir bereitgestellten Puffer liest, und sperrt den Stream für diesen Reader.

seit JavaScript Chrome/Edge 89+, Firefox 102+, Safari 18.4+, Node. Kategorie: webapi

Signatur

new ReadableStreamBYOBReader(stream)

Beschreibung

Der Konstruktor ReadableStreamBYOBReader() erzeugt einen Reader für einen Byte-Stream, also einen ReadableStream, der mit type: "bytes" angelegt wurde. Anders als der Standard-Reader bekommst du keine vom Stream erzeugten Chunks. Stattdessen übergibst du bei jedem read() eine eigene ArrayBufferView (z. B. Uint8Array), und der Stream schreibt die Bytes direkt dort hinein. So vermeidest du unnötige Kopien und Speicherzuweisungen, weil du einen Puffer immer wieder verwenden kannst.

Mit dem Erstellen wird der Stream gesperrt (stream.locked === true). Solange der Reader die Sperre hält, kann kein anderer Reader auf den Stream zugreifen. Mit reader.releaseLock() gibst du die Sperre wieder frei.

In der Praxis bekommst du einen solchen Reader meist über stream.getReader({ mode: "byob" }). Das ist gleichwertig zum direkten Aufruf des Konstruktors. BYOB-Reader eignen sich besonders für Binärprotokolle, Dateiformate mit festen Header-Größen und das Lesen großer Datenmengen mit wenig Speicher, etwa aus fetch()-Antworten (response.body ist ein Byte-Stream) oder aus eigenen Byte-Quellen.

Wichtig: Der Puffer, den du an read() übergibst, wird übertragen („transferred“) und ist danach abgekoppelt (detached). Arbeite deshalb immer mit value bzw. value.buffer aus dem Ergebnis weiter.

Parameter

Name Typ Default Beschreibung
$stream Pflicht ReadableStream Der zu lesende Byte-Stream. Er muss mit type: "bytes" erzeugt worden sein (also einen ReadableByteStreamController haben) und darf noch nicht gesperrt sein.

Rückgabewert

Typ
ReadableStreamBYOBReader
Beschreibung
Ein neuer Reader, der an stream gebunden ist und ihn sperrt. Er bietet read(view), cancel(), releaseLock() und das Promise closed.

Beispiele

Reader für einen eigenen Byte-Stream erzeugen

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

const reader = new ReadableStreamBYOBReader(stream);
console.log(stream.locked);

// Eigenen Puffer mit 8 Bytes bereitstellen
const { value, done } = await reader.read(new Uint8Array(8));
console.log(value, done);

reader.releaseLock();
console.log(stream.locked);
true Uint8Array(5) [1, 2, 3, 4, 5] false false

Genau N Bytes aus einer fetch-Antwort lesen (Puffer wiederverwenden)

const readExactly = async (reader, size) => {
  let buffer = new ArrayBuffer(size);
  let offset = 0;

  while (offset < size) {
    const { value, done } = await reader.read(
      new Uint8Array(buffer, offset, size - offset)
    );
    if (value) {
      // Der alte Puffer ist jetzt abgekoppelt, also mit dem zurückgegebenen weiterarbeiten
      buffer = value.buffer;
      offset += value.byteLength;
    }
    if (done) break;
  }
  return new Uint8Array(buffer, 0, offset);
};

const response = await fetch("/daten.bin");
const reader = new ReadableStreamBYOBReader(response.body);

// Beispiel: 16 Byte langen Datei-Header lesen
const header = await readExactly(reader, 16);
console.log(`Header: ${header.byteLength} Bytes`);
await reader.cancel(); // Rest wird nicht gebraucht
Header: 16 Bytes

Fehlerfälle: kein Byte-Stream oder Stream schon gesperrt

const normalStream = new ReadableStream({
  start(controller) {
    controller.enqueue("Text");
    controller.close();
  }
});

try {
  new ReadableStreamBYOBReader(normalStream);
} catch (err) {
  console.log(err.name); // kein type: "bytes"
}

const byteStream = new ReadableStream({ type: "bytes" });
const first = byteStream.getReader({ mode: "byob" });

try {
  new ReadableStreamBYOBReader(byteStream);
} catch (err) {
  console.log(err.name); // schon gesperrt
}
TypeError TypeError

// Wichtig · Fallstricke

  • TypeError: Der Konstruktor wirft einen Fehler, wenn stream kein Byte-Stream ist (also ohne type: "bytes" erzeugt wurde) oder bereits gesperrt ist. Das prüfst du vorher mit stream.locked.
  • Abgekoppelte Puffer: Nach read(view) ist view.buffer nicht mehr nutzbar (byteLength === 0). Verwende immer result.value.buffer für den nächsten Lesevorgang.
  • Teilweise gefüllt: read() kann weniger Bytes liefern, als die übergebene View fasst. Brauchst du eine feste Anzahl, liest du in einer Schleife weiter (siehe Beispiel) oder nutzt in neueren Browsern die Option read(view, { min }).
  • Die View darf nicht leer sein (byteLength > 0), sonst wird das Promise mit einem TypeError abgelehnt.
  • Kompatibilität: Chromium hat Byte-Streams und BYOB-Reader seit Version 89, Firefox seit 102, Safari erst seit 18.4. In älteren Safari-Versionen ist response.body kein Byte-Stream. Mach dort eine Funktionsprüfung und falle auf getReader() zurück. In Node.js stehen beide als Globals ab Version 18 zur Verfügung, vorher über stream/web.