CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-web-streams-polyfill

Web Streams polyfill and ponyfill implementation based on the WHATWG specification

Pending
Overview
Eval results
Files

writable-streams.mddocs/

Writable Streams

Writable stream functionality for creating data destinations that can be written to, with backpressure support and error handling.

Capabilities

WritableStream Class

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);
  }
});

WritableStreamDefaultWriter

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();
}

WritableStreamDefaultController

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;
}

Underlying Sink Types

UnderlyingSink Interface

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`);
  }
});

Callback Types

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

docs

index.md

queuing-strategies.md

readable-streams.md

transform-streams.md

writable-streams.md

tile.json