Node.js v26.10.0 documentation
- Node.js v26.10.0
- Table of contents
- Stream
- Organization of this document
- Types of streams
- API for stream consumers
- Writable streams
- Class:
stream.Writable- Event:
'close' - Event:
'drain' - Event:
'error' - Event:
'finish' - Event:
'pipe' - Event:
'unpipe' writable.cork()writable.destroy([error])writable.closedwritable.destroyedwritable.end([chunk[, encoding]][, callback])writable.setDefaultEncoding(encoding)writable.uncork()writable.writablewritable.writableAbortedwritable.writableEndedwritable.writableCorkedwritable.erroredwritable.writableFinishedwritable.writableHighWaterMarkwritable.writableLengthwritable.writableNeedDrainwritable.writableObjectModewritable[Symbol.asyncDispose]()writable.write(chunk[, encoding][, callback])
- Event:
- Class:
- Readable streams
- Two reading modes
- Three states
- Choose one API style
- Class:
stream.Readable- Event:
'close' - Event:
'data' - Event:
'end' - Event:
'error' - Event:
'pause' - Event:
'readable' - Event:
'resume' readable.destroy([error])readable.closedreadable.destroyedreadable.isPaused()readable.pause()readable.pipe(destination[, options])readable.read([size])readable.readablereadable.readableAbortedreadable.readableDidReadreadable.readableEncodingreadable.readableEndedreadable.erroredreadable.readableFlowingreadable.readableHighWaterMarkreadable.readableLengthreadable.readableObjectModereadable.resume()readable.setEncoding(encoding)readable.unpipe([destination])readable.unshift(chunk[, encoding])readable.wrap(stream)readable[Symbol.asyncIterator]()readable[Symbol.for('Stream.toAsyncStreamable')]()readable[Symbol.asyncDispose]()readable.compose(stream[, options])readable.iterator([options])readable.map(fn[, options])readable.filter(fn[, options])readable.forEach(fn[, options])readable.toArray([options])readable.some(fn[, options])readable.find(fn[, options])readable.every(fn[, options])readable.flatMap(fn[, options])readable.drop(limit[, options])readable.take(limit[, options])readable.reduce(fn[, initial[, options]])
- Event:
- Duplex and transform streams
stream.finished(stream[, options], callback)stream.pipeline(source[, ...transforms], destination, callback)stream.pipeline(streams, callback)stream.compose(...streams)stream.isDestroyed(stream)stream.isErrored(stream)stream.isReadable(stream)stream.isWritable(stream)stream.Readable.from(iterable[, options])stream.Readable.fromWeb(readableStream[, options])stream.Readable.isDisturbed(stream)stream.Readable.toWeb(streamReadable[, options])stream.Writable.fromWeb(writableStream[, options])stream.Writable.toWeb(streamWritable)stream.Duplex.from(src)stream.Duplex.fromWeb(pair[, options])stream.Duplex.toWeb(streamDuplex[, options])stream.addAbortSignal(signal, stream)stream.getDefaultHighWaterMark(objectMode)stream.setDefaultHighWaterMark(objectMode, value)
- Writable streams
- API for stream implementers
- Additional notes
- Stream
- Index
- About this documentation
- Usage and example
- Assertion testing
- Asynchronous context tracking
- Async hooks
- Benchmark runner
- Buffer
- C++ addons
- C/C++ addons with Node-API
- C++ embedder API
- Child processes
- Cluster
- Command-line options
- Console
- Crypto
- Debugger
- Deprecated APIs
- Diagnostics Channel
- DNS
- Domain
- Environment Variables
- Errors
- Events
- File system
- FFI
- Globals
- HTTP
- HTTP/2
- HTTPS
- Inspector
- Internationalization
- Iterable Streams API
- Modules: CommonJS modules
- Modules: ECMAScript modules
- Modules:
node:moduleAPI - Modules: Packages
- Modules: TypeScript
- Net
- OS
- Path
- Performance hooks
- Permissions
- Process
- Punycode
- Query strings
- Readline
- REPL
- Report
- Single executable applications
- SQLite
- Stream
- String decoder
- Test runner
- Timers
- TLS/SSL
- Trace events
- TTY
- UDP/datagram
- URL
- Utilities
- V8
- Virtual File System
- VM
- WASI
- Web Crypto API
- Web Streams API
- Worker threads
- Zlib
- Other versions
- Options
Stream#
Stability: 2 - Stable
A stream is an abstract interface for working with streaming data in Node.js.
The node:stream module provides an API for implementing the stream interface.
There are many stream objects provided by Node.js. For instance, a
request to an HTTP server and process.stdout
are both stream instances.
Streams can be readable, writable, or both. All streams are instances of
EventEmitter.
To access the node:stream module:
const stream = require('node:stream');
The node:stream module is useful for creating new types of stream instances.
It is usually not necessary to use the node:stream module to consume streams.
Organization of this document#
This document contains two primary sections and a third section for notes. The first section explains how to use existing streams within an application. The second section explains how to create new types of streams.
Types of streams#
There are four fundamental stream types within Node.js:
Writable: streams to which data can be written (for example,fs.createWriteStream()).Readable: streams from which data can be read (for example,fs.createReadStream()).Duplex: streams that are bothReadableandWritable(for example,net.Socket).Transform:Duplexstreams that can modify or transform the data as it is written and read (for example,zlib.createDeflate()).
Additionally, this module includes the utility functions
stream.duplexPair(),
stream.pipeline(),
stream.finished()
stream.Readable.from(), and
stream.addAbortSignal().
Streams Promises API#
The stream/promises API provides an alternative set of asynchronous utility
functions for streams that return Promise objects rather than using
callbacks. The API is accessible via require('node:stream/promises')
or require('node:stream').promises.
stream.pipeline(streams[, options])#
stream.pipeline(source[, ...transforms], destination[, options])#
streams{Stream[]|Iterable[]|AsyncIterable[]|Function[]| ReadableStream[]|WritableStream[]|TransformStream[]}source<Stream>|<Iterable>|<AsyncIterable>|<Function>|<ReadableStream>- Returns:
<Promise>|<AsyncIterable>
- Returns:
...transforms<Stream>|<Function>|<TransformStream>source<AsyncIterable>- Returns:
<Promise>|<AsyncIterable>
destination<Stream>|<Function>|<WritableStream>source<AsyncIterable>- Returns:
<Promise>|<AsyncIterable>
options<Object>Pipeline optionssignal<AbortSignal>end<boolean>End the destination stream when the source stream ends. Transform streams are always ended, even if this value isfalse. Default:true.
- Returns:
<Promise>Fulfills when the pipeline is complete.
const { pipeline } = require('node:stream/promises'); const fs = require('node:fs'); const zlib = require('node:zlib'); async function run() { await pipeline( fs.createReadStream('archive.tar'), zlib.createGzip(), fs.createWriteStream('archive.tar.gz'), ); console.log('Pipeline succeeded.'); } run().catch(console.error);import { pipeline } from 'node:stream/promises'; import { createReadStream, createWriteStream } from 'node:fs'; import { createGzip } from 'node:zlib'; await pipeline( createReadStream('archive.tar'), createGzip(), createWriteStream('archive.tar.gz'), ); console.log('Pipeline succeeded.');
To use an AbortSignal, pass it inside an options object, as the last argument.
When the signal is aborted, destroy will be called on the underlying pipeline,
with an AbortError.
const { pipeline } = require('node:stream/promises'); const fs = require('node:fs'); const zlib = require('node:zlib'); async function run() { const ac = new AbortController(); const signal = ac.signal; setImmediate(() => ac.abort()); await pipeline( fs.createReadStream('archive.tar'), zlib.createGzip(), fs.createWriteStream('archive.tar.gz'), { signal }, ); } run().catch(console.error); // AbortErrorimport { pipeline } from 'node:stream/promises'; import { createReadStream, createWriteStream } from 'node:fs'; import { createGzip } from 'node:zlib'; const ac = new AbortController(); const { signal } = ac; setImmediate(() => ac.abort()); try { await pipeline( createReadStream('archive.tar'), createGzip(), createWriteStream('archive.tar.gz'), { signal }, ); } catch (err) { console.error(err); // AbortError }
The pipeline API also supports async generators:
const { pipeline } = require('node:stream/promises'); const fs = require('node:fs'); async function run() { await pipeline( fs.createReadStream('lowercase.txt'), async function* (source, { signal }) { source.setEncoding('utf8'); // Work with strings rather than `Buffer`s. for await (const chunk of source) { yield await processChunk(chunk, { signal }); } }, fs.createWriteStream('uppercase.txt'), ); console.log('Pipeline succeeded.'); } run().catch(console.error);import { pipeline } from 'node:stream/promises'; import { createReadStream, createWriteStream } from 'node:fs'; await pipeline( createReadStream('lowercase.txt'), async function* (source, { signal }) { source.setEncoding('utf8'); // Work with strings rather than `Buffer`s. for await (const chunk of source) { yield await processChunk(chunk, { signal }); } }, createWriteStream('uppercase.txt'), ); console.log('Pipeline succeeded.');
Remember to handle the signal argument passed into the async generator.
Especially in the case where the async generator is the source for the
pipeline (i.e. first argument) or the pipeline will never complete.
const { pipeline } = require('node:stream/promises'); const fs = require('node:fs'); async function run() { await pipeline( async function* ({ signal }) { await someLongRunningfn({ signal }); yield 'asd'; }, fs.createWriteStream('uppercase.txt'), ); console.log('Pipeline succeeded.'); } run().catch(console.error);import { pipeline } from 'node:stream/promises'; import fs from 'node:fs'; await pipeline( async function* ({ signal }) { await someLongRunningfn({ signal }); yield 'asd'; }, fs.createWriteStream('uppercase.txt'), ); console.log('Pipeline succeeded.');
The pipeline API provides callback version:
stream.finished(stream[, options])#
stream<Stream>|<ReadableStream>|<WritableStream>A readable and/or writable stream/webstream.options<Object>error<boolean>|<undefined>readable<boolean>|<undefined>writable<boolean>|<undefined>signal<AbortSignal>|<undefined>cleanup<boolean>|<undefined>Iftrue, removes the listeners registered by this function before the promise is fulfilled. Default:false.
- Returns:
<Promise>Fulfills when the stream is no longer readable or writable.
const { finished } = require('node:stream/promises'); const fs = require('node:fs'); const rs = fs.createReadStream('archive.tar'); async function run() { await finished(rs); console.log('Stream is done reading.'); } run().catch(console.error); rs.resume(); // Drain the stream.import { finished } from 'node:stream/promises'; import { createReadStream } from 'node:fs'; const rs = createReadStream('archive.tar'); async function run() { await finished(rs); console.log('Stream is done reading.'); } run().catch(console.error); rs.resume(); // Drain the stream.
The finished API also provides a callback version.
stream.finished() leaves dangling event listeners (in particular
'error', 'end', 'finish' and 'close') after the returned promise is
resolved or rejected. The reason for this is so that unexpected 'error'
events (due to incorrect stream implementations) do not cause unexpected
crashes. If this is unwanted behavior then options.cleanup should be set to
true:
await finished(rs, { cleanup: true });
Object mode#
All streams created by Node.js APIs operate exclusively on strings, <Buffer>,
<TypedArray> and <DataView> objects:
StringsandBuffersare the most common types used with streams.TypedArrayandDataViewlets you handle binary data with types likeInt32ArrayorUint8Array. When you write a TypedArray or DataView to a stream, Node.js processes the raw bytes.
It is possible, however, for stream
implementations to work with other types of JavaScript values (with the
exception of null, which serves a special purpose within streams).
Such streams are considered to operate in "object mode".
Stream instances are switched into object mode using the objectMode option
when the stream is created. Attempting to switch an existing stream into
object mode is not safe.
Buffering#
Both Writable and Readable streams will store data in an internal
buffer.
The amount of data potentially buffered depends on the highWaterMark option
passed into the stream's constructor. For normal streams, the highWaterMark
option specifies a total number of bytes. For streams operating
in object mode, the highWaterMark specifies a total number of objects. For
streams operating on (but not decoding) strings, the highWaterMark specifies
a total number of UTF-16 code units.
Data is buffered in Readable streams when the implementation calls
stream.push(chunk). If the consumer of the Stream does not
call stream.read(), the data will sit in the internal
queue until it is consumed.
Once the total size of the internal read buffer reaches the threshold specified
by highWaterMark, the stream will temporarily stop reading data from the
underlying resource until the data currently buffered can be consumed (that is,
the stream will stop calling the internal readable._read() method that is
used to fill the read buffer).
Data is buffered in Writable streams when the
writable.write(chunk) method is called repeatedly. While the
total size of the internal write buffer is below the threshold set by
highWaterMark, calls to writable.write() will return true. Once
the size of the internal buffer reaches or exceeds the highWaterMark, false
will be returned.
A key goal of the stream API, particularly the stream.pipe() method,
is to limit the buffering of data to acceptable levels such that sources and
destinations of differing speeds will not overwhelm the available memory.
The highWaterMark option is a threshold, not a limit: it dictates the amount
of data that a stream buffers before it stops asking for more data. It does not
enforce a strict memory limitation in general. Specific stream implementations
may choose to enforce stricter limits but doing so is optional.
Because Duplex and Transform streams are both Readable and
Writable, each maintains two separate internal buffers used for reading and
writing, allowing each side to operate independently of the other while
maintaining an appropriate and efficient flow of data. For example,
net.Socket instances are Duplex streams whose Readable side allows
consumption of data received from the socket and whose Writable side allows
writing data to the socket. Because data may be written to the socket at a
faster or slower rate than data is received, each side should
operate (and buffer) independently of the other.
The mechanics of the internal buffering are an internal implementation detail
and may be changed at any time. However, for certain advanced implementations,
the internal buffers can be retrieved using writable.writableBuffer or
readable.readableBuffer. Use of these undocumented properties is discouraged.
API for stream consumers#
Almost all Node.js applications, no matter how simple, use streams in some manner. The following is an example of using streams in a Node.js application that implements an HTTP server:
const http = require('node:http');
const server = http.createServer((req, res) => {
// `req` is an http.IncomingMessage, which is a readable stream.
// `res` is an http.ServerResponse, which is a writable stream.
let body = '';
// Get the data as utf8 strings.
// If an encoding is not set, Buffer objects will be received.
req.setEncoding('utf8');
// Readable streams emit 'data' events once a listener is added.
req.on('data', (chunk) => {
body += chunk;
});
// The 'end' event indicates that the entire body has been received.
req.on('end', () => {
try {
const data = JSON.parse(body);
// Write back something interesting to the user:
res.write(typeof data);
res.end();
} catch (er) {
// uh oh! bad json!
res.statusCode = 400;
return res.end(`error: ${er.message}`);
}
});
});
server.listen(1337);
// $ curl localhost:1337 -d "{}"
// object
// $ curl localhost:1337 -d "\"foo\""
// string
// $ curl localhost:1337 -d "not json"
// error: Unexpected token 'o', "not json" is not valid JSON
Writable streams (such as res in the example) expose methods such as
write() and end() that are used to write data onto the stream.
Readable streams use the EventEmitter API for notifying application
code when data is available to be read off the stream. That available data can
be read from the stream in multiple ways.
Both Writable and Readable streams use the EventEmitter API in
various ways to communicate the current state of the stream.
Duplex and Transform streams are both Writable and
Readable.
Applications that are either writing data to or consuming data from a stream
are not required to implement the stream interfaces directly and will generally
have no reason to call require('node:stream').
Developers wishing to implement new types of streams should refer to the section API for stream implementers.
Writable streams#
Writable streams are an abstraction for a destination to which data is written.
Examples of Writable streams include:
- HTTP requests, on the client
- HTTP responses, on the server
- fs write streams
- zlib streams
- crypto streams
- TCP sockets
- child process stdin
process.stdout,process.stderr
Some of these examples are actually Duplex streams that implement the
Writable interface.
All Writable streams implement the interface defined by the
stream.Writable class.
While specific instances of Writable streams may differ in various ways,
all Writable streams follow the same fundamental usage pattern as illustrated
in the example below:
const myStream = getWritableStreamSomehow();
myStream.write('some data');
myStream.write('some more data');
myStream.end('done writing data');
Class: stream.Writable#
Event: 'close'#
The 'close' event is emitted when the stream and any of its underlying
resources (a file descriptor, for example) have been closed. The event indicates
that no more events will be emitted, and no further computation will occur.
A Writable stream will always emit the 'close' event if it is
created with the emitClose option.
Event: 'drain'#
If a call to stream.write(chunk) returns false, the
'drain' event will be emitted when it is appropriate to resume writing data
to the stream.
// Write the data to the supplied writable stream one million times.
// Be attentive to back-pressure.
function writeOneMillionTimes(writer, data, encoding, callback) {
let i = 1000000;
write();
function write() {
let ok = true;
do {
i--;
if (i === 0) {
// Last time!
writer.write(data, encoding, callback);
} else {
// See if we should continue, or wait.
// Don't pass the callback, because we're not done yet.
ok = writer.write(data, encoding);
}
} while (i > 0 && ok);
if (i > 0) {
// Had to stop early!
// Write some more once it drains.
writer.once('drain', write);
}
}
}
Event: 'error'#
- Type:
<Error>
The 'error' event is emitted if an error occurred while writing or piping
data. The listener callback is passed a single Error argument when called.
The stream is closed when the 'error' event is emitted unless the