Start · Sprachen · JavaScript · Referenz · ReadableStreamBYOBRequest.respond()

ReadableStreamBYOBRequest.respond()

Methode

Teilt dem lesbaren Bytestrom mit, dass <code>bytesWritten</code> Bytes in den Puffer <code>byobRequest.view</code> geschrieben wurden, und erfüllt damit die anstehende BYOB-Leseanforderung.

seit JavaScript Baseline 2023: Chrome 89, Firefox 102, Safari 16.4 Kategorie: webapi

Signatur

ReadableStreamBYOBRequest.prototype.respond(bytesWritten)

Beschreibung

respond() ist das Gegenstück zum BYOB-Lesen (Bring Your Own Buffer): Ruft ein Konsument ReadableStreamBYOBReader.read(view) auf, stellt der Strom der Quelle über controller.byobRequest einen Ausschnitt dieses Puffers bereit. Die zugrunde liegende Quelle schreibt die Daten direkt in byobRequest.view und meldet mit respond(bytesWritten), wie viele Bytes gültig sind. So werden Kopien vermieden, was bei großen Binärdaten (Dateien, Netzwerk-Sockets, Dekompression) Speicher und Rechenzeit spart.

Nach dem Aufruf wird der zugrunde liegende ArrayBuffer übertragen (transferiert): Die bisherige view ist danach abgekoppelt (byteLength 0), und die Anforderung ist erledigt. Der Konsument erhält die Daten als neue View über denselben Speicher im Ergebnis von read(). Es dürfen weniger Bytes gemeldet werden, als die View fasst. Der Rest bleibt dann für eine spätere Antwort offen, sofern der Reader eine Mindestmenge verlangt hat.

Verwende respond(), wenn du in die bereitgestellte View geschrieben hast. Hast du die Daten dagegen in einem eigenen Puffer, nimm respondWithNewView() oder controller.enqueue(). Ist der Strom mit controller.close() geschlossen worden, während noch eine BYOB-Anforderung offen ist, muss sie mit respond(0) abgeschlossen werden. Nur so wird der wartende read()-Aufruf mit done: true aufgelöst.

Parameter

Name Typ Default Beschreibung
$bytesWritten Pflicht number Anzahl der Bytes, die ab dem Anfang von byobRequest.view geschrieben wurden. Im Zustand readable muss der Wert größer als 0 sein und darf view.byteLength nicht übersteigen. Nach controller.close() muss er genau 0 sein.

Rückgabewert

Typ
undefined
Beschreibung
Kein Rückgabewert. Als Wirkung wird die anstehende read()-Promise des BYOB-Readers erfüllt, sobald genug Bytes vorliegen.

Beispiele

Bytequelle, die direkt in den Puffer des Konsumenten schreibt

const data = new TextEncoder().encode("Hallo BYOB-Welt!");
let offset = 0;

const stream = new ReadableStream({
  type: "bytes",
  pull(controller) {
    const request = controller.byobRequest;
    if (offset >= data.length) {
      controller.close();
      request?.respond(0); // offene Anforderung nach close() abschließen
      return;
    }
    const view = request.view; // Uint8Array über den Puffer des Lesers
    const n = Math.min(view.byteLength, data.length - offset);
    view.set(data.subarray(offset, offset + n));
    offset += n;
    request.respond(n); // n Bytes sind gültig
  }
});

const reader = stream.getReader({ mode: "byob" });
let buffer = new ArrayBuffer(5);
while (true) {
  const { value, done } = await reader.read(new Uint8Array(buffer));
  if (done) break;
  console.log(new TextDecoder().decode(value));
  buffer = value.buffer; // übertragenen Puffer wiederverwenden
}
Hallo BYOB -Welt !

Zufallsbytes mit autoAllocateChunkSize (auch für Standard-Reader)

const randomStream = new ReadableStream({
  type: "bytes",
  autoAllocateChunkSize: 16, // byobRequest existiert auch beim Standard-Reader
  pull(controller) {
    const { view } = controller.byobRequest;
    crypto.getRandomValues(view);
    controller.byobRequest.respond(view.byteLength);
  }
});

const reader = randomStream.getReader();
const { value } = await reader.read();
console.log(value.byteLength);
reader.cancel();
16

Fehlerfall: mehr Bytes melden als die View fasst

const stream = new ReadableStream({
  type: "bytes",
  pull(controller) {
    const request = controller.byobRequest;
    try {
      request.respond(request.view.byteLength + 1);
    } catch (err) {
      console.log(err.name);
      controller.error(err);
    }
  }
});

const reader = stream.getReader({ mode: "byob" });
await reader.read(new Uint8Array(4)).catch((e) => console.log("Lesen fehlgeschlagen:", e.name));
RangeError Lesen fehlgeschlagen: RangeError

// Wichtig · Fallstricke

  • Nur einmal aufrufen: Nach respond() ist die Anforderung erledigt, und byobRequest.view ist null. Ein zweiter Aufruf löst einen TypeError aus. Hol dir für die nächste Anforderung ein neues controller.byobRequest.
  • Abgekoppelte View: Referenzen auf die alte view oder ihren buffer sind nach dem Aufruf unbrauchbar (byteLength 0). Schreib nichts mehr hinein.
  • Ausnahmen: TypeError, wenn die Anforderung nicht mehr zum Controller gehört, der Puffer abgekoppelt ist oder im Zustand readable 0 übergeben wird. RangeError, wenn bytesWritten größer als die View ist oder nach close() ungleich 0 ist.
  • controller.byobRequest ist null, wenn keine BYOB-Leseanforderung ansteht. Das ist z. B. beim Standard-Reader ohne autoAllocateChunkSize der Fall. Prüfe den Wert daher vor dem Zugriff.
  • Funktioniert nur bei Strömen mit type: \"bytes\". Unterstützung gibt es in allen aktuellen Browsern (Safari erst ab 16.4) und in Node.js über stream/web bzw. global ab Version 18.