Web Streams polyfill and ponyfill implementation based on the WHATWG specification
—
Writable stream functionality for creating data destinations that can be written to, with backpressure support and error handling.
The main writable stream class that represents a destination for data, into which you can write.
/**
* A writable stream represents a destination for data, into which you can write.
*/
class WritableStream<W = any> {
constructor(underlyingSink?: UnderlyingSink<W>, strategy?: QueuingStrategy<W>);
/** Returns whether or not the writable stream is locked to a writer */
readonly locked: boolean;
/** Aborts the stream, signaling that the producer can no longer successfully write to the stream */
abort(reason?: any): Promise<void>;
/** Closes the stream. The underlying sink will finish processing any previously-written chunks */
close(): Promise<void>;
/** Creates a WritableStreamDefaultWriter and locks the stream to the new writer */
getWriter(): WritableStreamDefaultWriter<W>;
}Usage Examples:
import { WritableStream } from "web-streams-polyfill";
// Create a writable stream that logs written chunks
const logStream = new WritableStream({
write(chunk) {
console.log("Received:", chunk);
},
close() {
console.log("Stream closed");
}
});
const writer = logStream.getWriter();
try {
await writer.write("Hello");
await writer.write("World");
await writer.close();
} finally {
writer.releaseLock();
}
// Create a writable stream that collects data
const chunks: string[] = [];
const collectStream = new WritableStream({
write(chunk) {
chunks.push(chunk);
}
});Default writer for writable streams that provides methods to write data and manage the stream's lock.
/**
* Default writer for writable streams
*/
class WritableStreamDefaultWriter<W> {
constructor(stream: WritableStream<W>);
/** Promise that will be fulfilled when the stream becomes closed or rejected if the stream ever errors */
readonly closed: Promise<undefined>;
/** Returns the desired size to fill the controlled stream's internal queue */
readonly desiredSize: number | null;
/** Promise that will be fulfilled when the desired size transitions from non-positive to positive */
readonly ready: Promise<undefined>;
/** Abort the writable stream, signaling that the producer can no longer write to the stream */
abort(reason?: any): Promise<void>;
/** Close the writable stream */
close(): Promise<void>;
/** Release the writer's lock on the corresponding stream */
releaseLock(): void;
/** Write a chunk to the writable stream */
write(chunk: W): Promise<void>;
}Usage Examples:
import { WritableStream } from "web-streams-polyfill";
const stream = new WritableStream({
write(chunk, controller) {
// Process the chunk
console.log("Processing:", chunk);
// Simulate some async work
return new Promise(resolve => setTimeout(resolve, 100));
}
});
const writer = stream.getWriter();
try {
// Wait for the stream to be ready before writing
await writer.ready;
await writer.write("First chunk");
await writer.write("Second chunk");
// Check backpressure
if (writer.desiredSize !== null && writer.desiredSize <= 0) {
await writer.ready; // Wait for backpressure to clear
}
await writer.close();
} finally {
writer.releaseLock();
}Controller provided to underlying sinks for managing the writable stream's internal state.
/**
* Controller for writable streams
*/
class WritableStreamDefaultController<W> {
/** The reason given for why the associated stream was aborted (deprecated, use signal instead) */
readonly abortReason: any;
/** AbortSignal that can be used to abort the pending write or close operation when the stream is aborted */
readonly signal: AbortSignal;
/** Error the controlled writable stream, making all future interactions with it fail */
error(error?: any): void;
}Configuration object for writable streams that defines how the stream processes written data.
interface UnderlyingSink<W = any> {
/** Called immediately during construction of the WritableStream */
start?: (controller: WritableStreamDefaultController<W>) => void | PromiseLike<void>;
/** Called when a new chunk of data is ready to be written to the underlying sink */
write?: (chunk: W, controller: WritableStreamDefaultController<W>) => void | PromiseLike<void>;
/** Called after the producer signals it is done writing chunks to the stream */
close?: () => void | PromiseLike<void>;
/** Called when the producer signals it is done writing chunks to the stream via an error */
abort?: (reason: any) => void | PromiseLike<void>;
/** Must be undefined for default writable streams */
type?: undefined;
}Usage Examples:
import { WritableStream } from "web-streams-polyfill";
// File-like writable stream
const fileWriter = new WritableStream({
start(controller) {
console.log("Starting file write operation");
},
async write(chunk, controller) {
// Simulate writing to a file
console.log(`Writing ${chunk.length} bytes to file`);
// Check for abort signal
if (controller.signal.aborted) {
throw new Error("Write operation was aborted");
}
// Simulate async file write
await new Promise(resolve => setTimeout(resolve, 10));
},
async close() {
console.log("File write completed, closing file");
},
async abort(reason) {
console.log("File write aborted:", reason);
// Clean up resources
}
});
// Network upload writable stream
const uploadStream = new WritableStream({
start(controller) {
this.uploadedBytes = 0;
},
async write(chunk, controller) {
try {
// Simulate network upload
await fetch('/upload', {
method: 'POST',
body: chunk,
signal: controller.signal
});
this.uploadedBytes += chunk.length;
console.log(`Uploaded ${this.uploadedBytes} total bytes`);
} catch (error) {
controller.error(error);
}
},
async close() {
console.log(`Upload completed: ${this.uploadedBytes} bytes total`);
}
});type UnderlyingSinkStartCallback<W> = (
controller: WritableStreamDefaultController<W>
) => void | PromiseLike<void>;
type UnderlyingSinkWriteCallback<W> = (
chunk: W,
controller: WritableStreamDefaultController<W>
) => void | PromiseLike<void>;
type UnderlyingSinkCloseCallback = () => void | PromiseLike<void>;
type UnderlyingSinkAbortCallback = (reason: any) => void | PromiseLike<void>;Install with Tessl CLI
npx tessl i tessl/npm-web-streams-polyfill