TransformStream
BaselineWidely available *
This feature is well established and works across many devices and browser versions. It’s been available across browsers since June 2022.
* Some parts of this feature may have varying levels of support.
Note: This feature is available inWeb Workers.
TheTransformStream
interface of theStreams API represents a concrete implementation of thepipe chaintransform stream concept.
It may be passed to theReadableStream.pipeThrough()
method in order to transform a stream of data from one format into another.For example, it might be used to decode (or encode) video frames, decompress data, or convert the stream from XML to JSON.
A transformation algorithm may be provided as an optional argument to the object constructor.If not supplied, data is not modified when piped through the stream.
TransformStream
is atransferable object.
Constructor
TransformStream()
Creates and returns a transform stream object, optionally specifying a transformation object and queuing strategies for the streams.
Instance properties
TransformStream.readable
Read onlyThe
readable
end of aTransformStream
.TransformStream.writable
Read onlyThe
writable
end of aTransformStream
.
Instance methods
None
Examples
Anything-to-uint8array stream
In the following example, a transform stream passes through all chunks it receives asUint8Array
values.
const transformContent = { start() {}, // required. async transform(chunk, controller) { chunk = await chunk; switch (typeof chunk) { case "object": // just say the stream is done I guess if (chunk === null) { controller.terminate(); } else if (ArrayBuffer.isView(chunk)) { controller.enqueue( new Uint8Array(chunk.buffer, chunk.byteOffset, chunk.byteLength), ); } else if ( Array.isArray(chunk) && chunk.every((value) => typeof value === "number") ) { controller.enqueue(new Uint8Array(chunk)); } else if ( typeof chunk.valueOf === "function" && chunk.valueOf() !== chunk ) { this.transform(chunk.valueOf(), controller); // hack } else if ("toJSON" in chunk) { this.transform(JSON.stringify(chunk), controller); } break; case "symbol": controller.error("Cannot send a symbol as a chunk part"); break; case "undefined": controller.error("Cannot send undefined as a chunk part"); break; default: controller.enqueue(this.textencoder.encode(String(chunk))); break; } }, flush() { /* do any destructor work here */ },};class AnyToU8Stream extends TransformStream { constructor() { super({ ...transformContent, textencoder: new TextEncoder() }); }}
Chaining multiple ReadableStreams together
This is a useful one, where multiple streams can be conjoined. Examples include building a PWA with progressive loading and progressive streaming.
let responses = [ /* conjoined response tree */];let { readable, writable } = new TransformStream();responses.reduce( (a, res, i, arr) => a.then(() => res.pipeTo(writable, { preventClose: i + 1 !== arr.length })), Promise.resolve(),);
Note that this is not resilient to other influences.
Specifications
Specification |
---|
Streams # ts-class |