0
# Writable Streams
1
2
Writable stream functionality for creating data destinations that can be written to, with backpressure support and error handling.
3
4
## Capabilities
5
6
### WritableStream Class
7
8
The main writable stream class that represents a destination for data, into which you can write.
9
10
```typescript { .api }
11
/**
12
* A writable stream represents a destination for data, into which you can write.
13
*/
14
class WritableStream<W = any> {
15
constructor(underlyingSink?: UnderlyingSink<W>, strategy?: QueuingStrategy<W>);
16
17
/** Returns whether or not the writable stream is locked to a writer */
18
readonly locked: boolean;
19
20
/** Aborts the stream, signaling that the producer can no longer successfully write to the stream */
21
abort(reason?: any): Promise<void>;
22
23
/** Closes the stream. The underlying sink will finish processing any previously-written chunks */
24
close(): Promise<void>;
25
26
/** Creates a WritableStreamDefaultWriter and locks the stream to the new writer */
27
getWriter(): WritableStreamDefaultWriter<W>;
28
}
29
```
30
31
**Usage Examples:**
32
33
```typescript
34
import { WritableStream } from "web-streams-polyfill";
35
36
// Create a writable stream that logs written chunks
37
const logStream = new WritableStream({
38
write(chunk) {
39
console.log("Received:", chunk);
40
},
41
close() {
42
console.log("Stream closed");
43
}
44
});
45
46
const writer = logStream.getWriter();
47
48
try {
49
await writer.write("Hello");
50
await writer.write("World");
51
await writer.close();
52
} finally {
53
writer.releaseLock();
54
}
55
56
// Create a writable stream that collects data
57
const chunks: string[] = [];
58
const collectStream = new WritableStream({
59
write(chunk) {
60
chunks.push(chunk);
61
}
62
});
63
```
64
65
### WritableStreamDefaultWriter
66
67
Default writer for writable streams that provides methods to write data and manage the stream's lock.
68
69
```typescript { .api }
70
/**
71
* Default writer for writable streams
72
*/
73
class WritableStreamDefaultWriter<W> {
74
constructor(stream: WritableStream<W>);
75
76
/** Promise that will be fulfilled when the stream becomes closed or rejected if the stream ever errors */
77
readonly closed: Promise<undefined>;
78
79
/** Returns the desired size to fill the controlled stream's internal queue */
80
readonly desiredSize: number | null;
81
82
/** Promise that will be fulfilled when the desired size transitions from non-positive to positive */
83
readonly ready: Promise<undefined>;
84
85
/** Abort the writable stream, signaling that the producer can no longer write to the stream */
86
abort(reason?: any): Promise<void>;
87
88
/** Close the writable stream */
89
close(): Promise<void>;
90
91
/** Release the writer's lock on the corresponding stream */
92
releaseLock(): void;
93
94
/** Write a chunk to the writable stream */
95
write(chunk: W): Promise<void>;
96
}
97
```
98
99
**Usage Examples:**
100
101
```typescript
102
import { WritableStream } from "web-streams-polyfill";
103
104
const stream = new WritableStream({
105
write(chunk, controller) {
106
// Process the chunk
107
console.log("Processing:", chunk);
108
109
// Simulate some async work
110
return new Promise(resolve => setTimeout(resolve, 100));
111
}
112
});
113
114
const writer = stream.getWriter();
115
116
try {
117
// Wait for the stream to be ready before writing
118
await writer.ready;
119
120
await writer.write("First chunk");
121
await writer.write("Second chunk");
122
123
// Check backpressure
124
if (writer.desiredSize !== null && writer.desiredSize <= 0) {
125
await writer.ready; // Wait for backpressure to clear
126
}
127
128
await writer.close();
129
} finally {
130
writer.releaseLock();
131
}
132
```
133
134
### WritableStreamDefaultController
135
136
Controller provided to underlying sinks for managing the writable stream's internal state.
137
138
```typescript { .api }
139
/**
140
* Controller for writable streams
141
*/
142
class WritableStreamDefaultController<W> {
143
/** The reason given for why the associated stream was aborted (deprecated, use signal instead) */
144
readonly abortReason: any;
145
146
/** AbortSignal that can be used to abort the pending write or close operation when the stream is aborted */
147
readonly signal: AbortSignal;
148
149
/** Error the controlled writable stream, making all future interactions with it fail */
150
error(error?: any): void;
151
}
152
```
153
154
## Underlying Sink Types
155
156
### UnderlyingSink Interface
157
158
Configuration object for writable streams that defines how the stream processes written data.
159
160
```typescript { .api }
161
interface UnderlyingSink<W = any> {
162
/** Called immediately during construction of the WritableStream */
163
start?: (controller: WritableStreamDefaultController<W>) => void | PromiseLike<void>;
164
165
/** Called when a new chunk of data is ready to be written to the underlying sink */
166
write?: (chunk: W, controller: WritableStreamDefaultController<W>) => void | PromiseLike<void>;
167
168
/** Called after the producer signals it is done writing chunks to the stream */
169
close?: () => void | PromiseLike<void>;
170
171
/** Called when the producer signals it is done writing chunks to the stream via an error */
172
abort?: (reason: any) => void | PromiseLike<void>;
173
174
/** Must be undefined for default writable streams */
175
type?: undefined;
176
}
177
```
178
179
**Usage Examples:**
180
181
```typescript
182
import { WritableStream } from "web-streams-polyfill";
183
184
// File-like writable stream
185
const fileWriter = new WritableStream({
186
start(controller) {
187
console.log("Starting file write operation");
188
},
189
190
async write(chunk, controller) {
191
// Simulate writing to a file
192
console.log(`Writing ${chunk.length} bytes to file`);
193
194
// Check for abort signal
195
if (controller.signal.aborted) {
196
throw new Error("Write operation was aborted");
197
}
198
199
// Simulate async file write
200
await new Promise(resolve => setTimeout(resolve, 10));
201
},
202
203
async close() {
204
console.log("File write completed, closing file");
205
},
206
207
async abort(reason) {
208
console.log("File write aborted:", reason);
209
// Clean up resources
210
}
211
});
212
213
// Network upload writable stream
214
const uploadStream = new WritableStream({
215
start(controller) {
216
this.uploadedBytes = 0;
217
},
218
219
async write(chunk, controller) {
220
try {
221
// Simulate network upload
222
await fetch('/upload', {
223
method: 'POST',
224
body: chunk,
225
signal: controller.signal
226
});
227
228
this.uploadedBytes += chunk.length;
229
console.log(`Uploaded ${this.uploadedBytes} total bytes`);
230
} catch (error) {
231
controller.error(error);
232
}
233
},
234
235
async close() {
236
console.log(`Upload completed: ${this.uploadedBytes} bytes total`);
237
}
238
});
239
```
240
241
## Callback Types
242
243
```typescript { .api }
244
type UnderlyingSinkStartCallback<W> = (
245
controller: WritableStreamDefaultController<W>
246
) => void | PromiseLike<void>;
247
248
type UnderlyingSinkWriteCallback<W> = (
249
chunk: W,
250
controller: WritableStreamDefaultController<W>
251
) => void | PromiseLike<void>;
252
253
type UnderlyingSinkCloseCallback = () => void | PromiseLike<void>;
254
255
type UnderlyingSinkAbortCallback = (reason: any) => void | PromiseLike<void>;
256
```