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

ReadableStreamBYOBReader.releaseLock()

Methode

Gibt die Sperre des BYOB-Readers auf seinem <code>ReadableStream</code> frei, damit ein anderer Reader den Stream übernehmen kann.

seit JavaScript Baseline 2023: Chrome 89, Edge 89, Firefox 102, Sa Kategorie: webapi

Signatur

ReadableStreamBYOBReader.prototype.releaseLock()

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

Typ
undefined
Beschreibung
Kein Rückgabewert. Die Methode gibt die Sperre sofort (synchron) frei.

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);
Uint8Array(4) [ 1, 2, 3, 4 ] true false Uint8Array(4) [ 5, 6, 7, 8 ]

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
Uint8Array(8) [ 137, 80, 78, 71, 13, 10, 26, 10 ] false

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);
}
read(): TypeError closed: TypeError

// Wichtig · Fallstricke

  • Verhalten hat sich geändert: Früher warf releaseLock() selbst einen TypeError, wenn noch read()-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 alle read()-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. Nach releaseLock() geht das auch über stream.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.body aus fetch(). Bei anderen Streams wirft getReader({ mode: "byob" }) einen TypeError.
  • 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".