Signatur
Beschreibung
Ein WritableStreamDefaultController wird nie selbst erzeugt. Der WritableStream-Konstruktor legt ihn automatisch an und übergibt ihn an die Methoden der zugrunde liegenden Senke (underlying sink): an start(controller) und an write(chunk, controller). Über den Controller steuert die Senke den Zustand des Streams von innen heraus.
Die Schnittstelle ist bewusst schlank:
controller.error(reason): versetzt den Stream in den Fehlerzustand. Danach schlagen alle weiteren Zugriffe über den Writer fehl, undwriter.closedwird mitreasonzurückgewiesen.controller.signal: einAbortSignal, das ausgelöst wird, sobald jemandwriter.abort()bzw.stream.abort()aufruft. So lassen sich laufende asynchrone Schreibvorgänge, etwafetch-Aufrufe, sofort abbrechen, statt zu warten, bis sie fertig sind.
Typische Einsatzfälle sind die Prüfung von Chunks mit gezieltem Fehlschlag, das Abbrechen von Netzwerk-Schreibvorgängen und das Weiterreichen externer Fehler, etwa einer geschlossenen WebSocket-Verbindung. Wenn man den Controller in start() in einer Variablen speichert, kann man error() auch außerhalb der Senken-Methoden aufrufen.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $reason | any | undefined | Parameter von controller.error(reason): der Fehlergrund, meist ein Error-Objekt. Er wird an wartende Promises des Writers weitergereicht. |
Rückgabewert
start() und write() der Senke übergeben. error() gibt undefined zurück, signal liefert ein AbortSignal.Beispiele
Ungültige Chunks mit controller.error() ablehnen
const log = [];
const stream = new WritableStream({
write(chunk, controller) {
if (typeof chunk !== 'string') {
// Stream dauerhaft in den Fehlerzustand versetzen
controller.error(new TypeError('Nur Strings erlaubt'));
return;
}
log.push(chunk);
}
});
const writer = stream.getWriter();
await writer.write('Hallo');
writer.write(42).catch(() => {});
try {
await writer.closed;
} catch (err) {
console.log('Stream fehlerhaft:', err.message);
}
console.log(log);
Laufenden fetch über controller.signal abbrechen
const stream = new WritableStream({
async write(chunk, controller) {
controller.signal.addEventListener('abort', () => {
console.log('Abgebrochen:', controller.signal.reason);
}, { once: true });
// Der Upload wird sofort beendet, wenn der Stream abgebrochen wird
await fetch('/api/log', {
method: 'POST',
body: chunk,
signal: controller.signal
});
}
});
const writer = stream.getWriter();
writer.write('Eintrag 1').catch(() => {});
setTimeout(() => writer.abort('Benutzer hat abgebrochen'), 50);
Controller speichern und externe Fehler weiterreichen
let ctrl;
const socket = new WebSocket('wss://example.com/feed');
const stream = new WritableStream({
start(controller) {
ctrl = controller;
// Erst schreiben, wenn die Verbindung steht
return new Promise((resolve, reject) => {
socket.addEventListener('open', resolve, { once: true });
socket.addEventListener('error', reject, { once: true });
});
},
write(chunk) {
socket.send(chunk);
},
close() {
socket.close();
}
});
// Verbindungsabbruch von außen -> Stream geht in den Fehlerzustand
socket.addEventListener('close', () => {
ctrl.error(new Error('WebSocket-Verbindung geschlossen'));
});
Direkte Instanziierung ist nicht erlaubt
try {
new WritableStreamDefaultController();
} catch (err) {
console.log(err instanceof TypeError);
}