Signatur
Beschreibung
Ein ReadableStreamBYOBReader („Bring Your Own Buffer“) wird mit stream.getReader({ mode: "byob" }) erzeugt und sperrt den Byte-Stream. Solange die Sperre besteht, kann niemand sonst lesen: Weitere getReader()-Aufrufe, pipeTo(), pipeThrough() und tee() werfen dann einen TypeError. Mit releaseLock() gibst du diese Sperre wieder frei. Danach ist stream.locked wieder false.
Das brauchst du vor allem, wenn du nur einen Teil eines Streams selbst lesen willst (z. B. einen Dateikopf mit fester Länge) und den Rest an anderen Code weitergibst: an einen Standard-Reader, an pipeTo() oder an eine Bibliothek. Die Daten, die noch nicht gelesen wurden, bleiben im Stream erhalten.
Nach der Freigabe ist der Reader nicht mehr nutzbar. Weitere Aufrufe von read() oder cancel() auf demselben Reader geben abgelehnte Promises zurück. Das Promise reader.closed wird mit einem TypeError abgelehnt, wenn der Stream zu diesem Zeitpunkt noch offen war. Laufende read()-Aufrufe, die noch auf Daten warten, werden nach aktueller Spezifikation ebenfalls mit einem TypeError abgelehnt.
Rückgabewert
Beispiele
Teil lesen, Sperre freigeben, Rest mit Standard-Reader lesen
// In einem ES-Modul (Top-Level-await)
const stream = new ReadableStream({
type: 'bytes',
start(controller) {
controller.enqueue(new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]));
controller.close();
}
});
const byobReader = stream.getReader({ mode: 'byob' });
const { value: header } = await byobReader.read(new Uint8Array(4));
console.log(header);
console.log(stream.locked);
byobReader.releaseLock();
console.log(stream.locked);
// Jetzt kann ein anderer Reader übernehmen
const reader = stream.getReader();
const { value: rest } = await reader.read();
console.log(rest);
Sperre sicher im finally-Block freigeben
// Liest einen Dateikopf mit fester Länge und gibt den Stream danach wieder frei
const readHeader = async (stream, length) => {
const reader = stream.getReader({ mode: 'byob' });
try {
let buffer = new ArrayBuffer(length);
let offset = 0;
while (offset < length) {
const { value, done } = await reader.read(
new Uint8Array(buffer, offset, length - offset)
);
if (done) break;
buffer = value.buffer; // der Puffer wird übertragen und neu vergeben
offset += value.byteLength;
}
return new Uint8Array(buffer, 0, offset);
} finally {
reader.releaseLock(); // auch bei Fehlern wieder freigeben
}
};
const response = await fetch('https://example.com/bild.png');
const header = await readHeader(response.body, 8);
console.log(header);
console.log(response.body.locked); // Stream kann weiterverarbeitet werden
Wartende read()-Aufrufe werden abgelehnt
// Byte-Stream, der (noch) keine Daten liefert
const stream = new ReadableStream({ type: 'bytes', pull() {} });
const reader = stream.getReader({ mode: 'byob' });
const pending = reader.read(new Uint8Array(16));
reader.releaseLock();
try {
await pending;
} catch (err) {
console.log('read():', err.name);
}
try {
await reader.closed;
} catch (err) {
console.log('closed:', err.name);
}
// Wichtig · Fallstricke
- Verhalten hat sich geändert: Früher warf
releaseLock()selbst einenTypeError, wenn nochread()-Aufrufe offen waren. Aktuelle Browser (Chrome/Edge 106+, Firefox 106+, Safari ab 18.4) und neue Node.js-Versionen lehnen stattdessen die offenen Leseaufrufe ab. Wenn du ältere Umgebungen unterstützen musst, warte vor der Freigabe alleread()-Promises ab. - Die Methode bricht den Stream nicht ab und schließt ihn nicht. Wenn du die übrigen Daten nicht mehr brauchst, rufe stattdessen
reader.cancel()auf. NachreleaseLock()geht das auch überstream.cancel(). - Du kannst
releaseLock()auf einem bereits freigegebenen Reader erneut aufrufen. Das hat keine Wirkung und löst keinen Fehler aus. - BYOB-Reader gibt es nur für Byte-Streams (
type: "bytes"), z. B.Response.bodyausfetch(). Bei anderen Streams wirftgetReader({ mode: "byob" })einenTypeError. - Nutze
try…finally, damit die Sperre auch bei Fehlern freigegeben wird. Sonst bleibt der Stream dauerhaft gesperrt. - Browser-Unterstützung: Safari unterstützt BYOB-Reader erst ab Version 18.4. Prüfe das bei Bedarf mit
typeof ReadableStreamBYOBReader !== "undefined".