Signatur
Beschreibung
Mit write() übergibst du einen einzelnen Datenblock an einen WritableStream. Den Writer bekommst du über stream.getWriter(). Er sperrt den Stream exklusiv für sich. Der Block landet zuerst in der internen Warteschlange des Streams und wird dann der Reihe nach an die write()-Methode des zugrundeliegenden Sinks weitergegeben. Das kann zum Beispiel eine Datei, ein Netzwerk-Socket oder ein eigener Verarbeitungsschritt sein.
Das zurückgegebene Promise wird erfüllt, sobald der Sink genau diesen Block verarbeitet hat. Es wird abgelehnt, wenn das Schreiben fehlschlägt oder der Stream vorher fehlerhaft wird, abgebrochen oder geschlossen wird. Ein erfülltes Promise heißt aber nicht unbedingt, dass die Daten schon an ihrem Ziel angekommen sind. Es heißt nur, dass der Sink den Block angenommen hat.
Für einen sauberen Gegendruck (Backpressure) solltest du nicht auf jedes write()-Promise warten, sondern vor jedem Schreiben auf writer.ready. Dieses Promise wird erfüllt, sobald in der Warteschlange wieder Platz ist (desiredSize > 0). So bleibt der Speicherverbrauch begrenzt, und mehrere Blöcke können trotzdem gleichzeitig unterwegs sein.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $chunk Pflicht | any | Der zu schreibende Datenblock. Welcher Typ erlaubt ist, hängt vom Sink ab: bei Byte-Sinks meist Uint8Array/ArrayBuffer, bei TextEncoderStream ein string, bei eigenen Sinks ein beliebiger Wert. |
Rückgabewert
undefined erfüllt wird, sobald der Sink den Block erfolgreich verarbeitet hat. Es wird abgelehnt (z. B. mit TypeError), wenn der Stream fehlerhaft, geschlossen oder im Schließvorgang ist oder der Writer seine Sperre schon freigegeben hat.Beispiele
Eigener Sink: Blöcke in einem Array sammeln
const received = [];
const stream = new WritableStream({
write(chunk) {
received.push(chunk);
},
close() {
console.log('Fertig:', received.join(' '));
}
});
const writer = stream.getWriter();
const run = async () => {
for (const word of ['Hallo', 'Streams', 'API']) {
await writer.write(word);
}
await writer.close();
};
run();
Backpressure beachten mit writer.ready
const stream = new WritableStream(
{
// Simuliert einen langsamen Sink
write: (chunk) => new Promise((resolve) => setTimeout(() => {
console.log('geschrieben:', chunk);
resolve();
}, 100))
},
new CountQueuingStrategy({ highWaterMark: 2 })
);
const writer = stream.getWriter();
const produce = async () => {
for (let i = 1; i <= 5; i++) {
await writer.ready; // warten, bis in der Warteschlange Platz ist
writer.write(`Block ${i}`).catch((err) => console.error('Fehler:', err));
}
await writer.close();
console.log('Stream geschlossen');
};
produce();
Text kodiert in einen Byte-Sink schreiben
const chunks = [];
const byteSink = new WritableStream({
write(chunk) {
chunks.push(chunk); // Uint8Array
},
close() {
const total = chunks.reduce((sum, c) => sum + c.byteLength, 0);
console.log(`Empfangene Bytes: ${total}`);
}
});
const encoder = new TextEncoderStream();
encoder.readable.pipeTo(byteSink);
const writer = encoder.writable.getWriter();
const send = async () => {
try {
await writer.write('Grüße ');
await writer.write('aus Köln');
await writer.close();
} catch (err) {
console.error('Schreiben fehlgeschlagen:', err);
} finally {
writer.releaseLock();
}
};
send();
// Wichtig · Fallstricke
- Nicht jedes write() einzeln abwarten: Ein
await writer.write()in einer Schleife ist korrekt, verarbeitet aber nur einen Block nach dem anderen. Für mehr Durchsatz wartest du aufwriter.readyund fängst diewrite()-Promises trotzdem mit.catch()ab. Sonst gibt es Warnungen über unbehandelte Ablehnungen (unhandled rejection). - Fehler machen den Stream unbrauchbar: Wirft der Sink einen Fehler oder lehnt er ab, geht der Stream in den Fehlerzustand. Alle weiteren
write()-Aufrufe werden dann abgelehnt. - Nach
writer.close()oderwriter.releaseLock()wird jedeswrite()mit einemTypeErrorabgelehnt. - Solange ein Writer existiert, ist der Stream gesperrt (
stream.locked === true).pipeTo()oder ein zweitesgetWriter()schlagen dann fehl. - Übergebene
ArrayBuffer-Views werden nicht automatisch kopiert. Ändere den Puffer nach dem Schreiben nicht, bis das Promise erfüllt ist. - Kompatibilität: Wird von Chrome, Edge, Firefox (ab 100) und Safari unterstützt. In Node.js ist die Methode über
stream/webverfügbar und ab Version 18 global.