Signatur
Beschreibung
respondWithNewView() wird in der Datenquelle eines lesbaren Bytestreams (new ReadableStream({ type: "bytes" })) verwendet. Die Methode beantwortet die aktuelle BYOB-Anforderung („bring your own buffer“). Anders als bei respond(bytesWritten) übergibt man dabei nicht einfach eine Anzahl von Bytes, sondern eine neue Ansicht (ArrayBufferView). Ihre byteLength gibt an, wie viele Bytes geschrieben wurden.
Das braucht man vor allem, wenn der ursprüngliche ArrayBuffer aus byobRequest.view während des Füllens übertragen wurde, also losgelöst („detached“) ist. Das passiert zum Beispiel mit ArrayBuffer.prototype.transfer(), mit structuredClone(…, { transfer }) oder mit postMessage an einen Worker. Die alte view ist danach unbrauchbar. Deshalb baut man auf dem zurückerhaltenen Puffer eine neue Ansicht und reicht sie mit respondWithNewView() weiter.
Für die neue Ansicht gelten strenge Regeln:
- Sie muss denselben
byteOffsethaben wie die ursprünglicheview. - Der zugrunde liegende Puffer muss dieselbe Gesamtlänge (
buffer.byteLength) haben wie der ursprüngliche Puffer. - Ihre
byteLengthdarf nicht größer sein als die ursprünglicheview.byteLength. - Wurde der Stream bereits geschlossen, muss die
byteLengthgenau0sein.
Nach dem Aufruf ist die Anforderung erledigt. controller.byobRequest ist dann null oder verweist auf eine neue Anforderung.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $view Pflicht | ArrayBufferView (z. B. Uint8Array, DataView) | Neue Ansicht auf den (ggf. übertragenen) Puffer mit den geschriebenen Daten. Der byteOffset muss dem der ursprünglichen byobRequest.view entsprechen. Die byteLength ist die Anzahl der geschriebenen Bytes. |
Rückgabewert
read()-Aufruf des BYOB-Readers wird mit einer Ansicht auf die geschriebenen Bytes erfüllt.Beispiele
Puffer mit transfer() übernehmen und beantworten
const stream = new ReadableStream({
type: "bytes",
pull(controller) {
const req = controller.byobRequest;
const { buffer, byteOffset, byteLength } = req.view;
// Puffer übernehmen – die alte req.view ist danach losgelöst
const owned = buffer.transfer();
const bytes = new Uint8Array(owned, byteOffset, byteLength);
const n = Math.min(4, byteLength);
for (let i = 0; i < n; i++) bytes[i] = 65 + i; // 'A'..'D'
// Neue Ansicht: gleicher Offset, Länge = geschriebene Bytes
req.respondWithNewView(new Uint8Array(owned, byteOffset, n));
}
});
const reader = stream.getReader({ mode: "byob" });
const { value, done } = await reader.read(new Uint8Array(8));
console.log(Array.from(value), done);
Asynchrones Füllen mit Transfer (Worker-Muster simuliert)
// Simuliert z. B. einen Worker: Puffer hin übertragen, gefüllt zurückbekommen
const fillElsewhere = async (buffer, offset, length) => {
const moved = structuredClone(buffer, { transfer: [buffer] });
const view = new Uint8Array(moved, offset, length);
const text = new TextEncoder().encode("Hallo");
const n = Math.min(text.length, length);
view.set(text.subarray(0, n));
return { buffer: moved, written: n };
};
let sent = false;
const stream = new ReadableStream({
type: "bytes",
async pull(controller) {
const req = controller.byobRequest;
const { buffer, byteOffset, byteLength } = req.view;
if (sent) {
controller.close();
// Nach close() muss mit einer Ansicht der Länge 0 geantwortet werden
req.respondWithNewView(new Uint8Array(buffer, byteOffset, 0));
return;
}
const result = await fillElsewhere(buffer, byteOffset, byteLength);
req.respondWithNewView(new Uint8Array(result.buffer, byteOffset, result.written));
sent = true;
}
});
const reader = stream.getReader({ mode: "byob" });
let r = await reader.read(new Uint8Array(16));
console.log(new TextDecoder().decode(r.value));
r = await reader.read(new Uint8Array(16));
console.log(r.done);
Typischer Fehler: falscher byteOffset
const stream = new ReadableStream({
type: "bytes",
pull(controller) {
const req = controller.byobRequest;
const { buffer, byteOffset } = req.view;
try {
// Offset weicht ab → RangeError
req.respondWithNewView(new Uint8Array(buffer, byteOffset + 1, 1));
} catch (err) {
console.log(err.name);
controller.error(err);
}
}
});
const reader = stream.getReader({ mode: "byob" });
reader.read(new Uint8Array(8)).catch(() => {});