Start · Sprachen · JavaScript · Referenz · ReadableStream.locked

ReadableStream.locked

Eigenschaft

Schreibgeschützter Boolean, der angibt, ob ein <code>ReadableStream</code> gerade an einen Leser (Reader) gebunden und damit gesperrt ist.

seit JavaScript Baseline: alle modernen Browser (seit 2019), Node. Kategorie: webapi

Signatur

get ReadableStream.prototype.locked

Beschreibung

Die Eigenschaft locked liefert true, sobald ein Leser über getReader() für den Stream angelegt wurde oder der Stream gerade per pipeTo() bzw. pipeThrough() weitergeleitet wird. Ein gesperrter Stream kann nur noch über diesen einen Leser gelesen werden. Weitere Aufrufe von getReader(), tee(), cancel() oder pipeTo() schlagen dann fehl.

Die Sperre sorgt dafür, dass immer nur ein Konsument die Daten eines Streams liest. Sonst könnten zwei Stellen im Code Teile (Chunks) „stehlen“ und die Daten würden unvollständig ankommen. Erst mit reader.releaseLock() wird der Stream wieder freigegeben, und locked ist danach wieder false.

In der Praxis nutzt man locked vor allem als Schutzprüfung: bevor man einen Stream an eine Hilfsfunktion übergibt, getReader() aufruft oder einen Response-Body weiterverarbeitet. Bei fetch gilt: response.body.locked ist true, sobald der Body gelesen wird, zum Beispiel über response.json().

Rückgabewert

Typ
boolean
Beschreibung
true, wenn der Stream an einen Leser gebunden ist oder gerade weitergeleitet wird (Pipe), sonst false.

Beispiele

Sperrzustand vor und nach getReader()

const stream = new ReadableStream({
  start(controller) {
    controller.enqueue('Hallo');
    controller.close();
  }
});

console.log(stream.locked); // false

const reader = stream.getReader();
console.log(stream.locked); // true

reader.releaseLock();
console.log(stream.locked); // false
false true false

Sicheres Lesen mit Schutzprüfung

const readAllText = async (stream) => {
  if (stream.locked) {
    throw new Error('Stream wird bereits von einem anderen Leser verwendet');
  }
  const reader = stream.pipeThrough(new TextDecoderStream()).getReader();
  let text = '';
  try {
    while (true) {
      const { done, value } = await reader.read();
      if (done) break;
      text += value;
    }
  } finally {
    reader.releaseLock();
  }
  return text;
};

const stream = new Blob(['Streams sind praktisch']).stream();
console.log(await readAllText(stream));
Streams sind praktisch

Response-Body nach dem Lesen gesperrt

const response = new Response('{"ok":true}');

console.log(response.body.locked); // false
const data = await response.json();
console.log(response.body.locked); // true
console.log(response.bodyUsed);    // true
console.log(data);
false true true { ok: true }

Sperre während pipeTo()

const source = new ReadableStream({
  start(c) { c.enqueue('a'); c.close(); }
});
const sink = new WritableStream({ write(chunk) { console.log('geschrieben:', chunk); } });

const piping = source.pipeTo(sink);
console.log(source.locked); // true
await piping;
console.log(source.locked); // false
true geschrieben: a false

// Wichtig · Fallstricke

  • Nur lesbar: Wenn du locked einen Wert zuweist, passiert nichts. Im Strict Mode wird ein TypeError geworfen, weil die Eigenschaft nur einen Getter hat.
  • Gesperrt heißt nicht beendet: locked sagt nichts darüber, ob der Stream geschlossen oder fehlerhaft ist. Auch ein vollständig gelesener Stream bleibt gesperrt, bis releaseLock() aufgerufen wird. Ob ein Stream geschlossen ist, erkennst du an reader.closed oder an done bei read().
  • Gesperrte Streams: getReader(), tee(), pipeTo() und pipeThrough() werfen bei einem gesperrten Stream einen TypeError. stream.cancel() gibt in diesem Fall ein abgelehntes Promise zurück. Ohne releaseLock() in einem finally-Block bleibt der Stream für immer gesperrt.
  • releaseLock() mit offenen Leseaufrufen: Laut aktueller Spezifikation werden offene read()-Promises dabei mit einem TypeError abgelehnt. Ältere Browserversionen haben stattdessen selbst einen Fehler geworfen.
  • Kompatibilität: Wird in allen modernen Browsern unterstützt. In Node.js steht die Eigenschaft über stream/web ab 16.5 zur Verfügung und ist ab 18 global verfügbar.