@@ -321,10 +321,17 @@ There are two ways to write data to a stream:
321321 up front or can be expressed as an iterable.
322322* ** Writer** β access [ ` stream.writer ` ] [ ] to push data incrementally. The
323323 writer exposes synchronous methods (` writeSync() ` , ` writevSync() ` ,
324- ` endSync() ` ) that return immediately, as well as async equivalents
325- (` write() ` , ` writev() ` , ` end() ` ) that wait for drain when backpressured.
324+ ` endSync() ` ) that return immediately, as well as asynchronous counterparts
325+ (` write() ` , ` writev() ` , ` end() ` ). The asynchronous ` write() ` and ` writev() `
326+ methods use the stream/iter strict backpressure policy: when the write buffer
327+ is full, they reject with ` ERR_INVALID_STATE ` instead of waiting for capacity.
328+ If a drain is already pending, ` end() ` waits for it before closing. Check
329+ ` writer.canWrite ` before writing. To wait for capacity, use ` ondrain() ` from
330+ ` node:stream/iter ` , then retry the write. The stream's ` onblocked ` callback
331+ reports that transport flow control has blocked progress, but does not
332+ signal that writer capacity is available again.
326333 ` writeSync() ` returns ` false ` when the write buffer is full; the caller
327- should wait for drain before retrying.
334+ should wait with ` ondrain() ` before retrying.
328335
329336These two approaches are mutually exclusive for a given stream.
330337
@@ -2449,12 +2456,16 @@ The Writer has the following methods:
24492456
24502457* ` writeSync(chunk) ` β Synchronous write. Returns ` true ` if accepted,
24512458 ` false ` if flow-controlled. Data is NOT accepted on ` false ` .
2452- * ` write(chunk[, options]) ` β Async write with drain wait. ` options.signal `
2453- is checked at entry but not observed during the write.
2459+ * ` write(chunk[, options]) ` β Async write. Rejects with ` ERR_INVALID_STATE `
2460+ when the stream is flow-controlled rather than waiting for capacity.
2461+ ` options.signal ` is checked at entry but not observed during the write.
24542462* ` writevSync(chunks) ` β Synchronous vectored write. All-or-nothing.
2455- * ` writev(chunks[, options]) ` β Async vectored write.
2463+ * ` writev(chunks[, options]) ` β Async vectored write. Rejects with
2464+ ` ERR_INVALID_STATE ` when the stream is flow-controlled rather than waiting
2465+ for capacity.
24562466* ` endSync() ` β Synchronous close. Returns total bytes or ` -1 ` .
2457- * ` end([options]) ` β Async close.
2467+ * ` end([options]) ` β Async close. If a drain is already pending, waits for it
2468+ before closing.
24582469* ` fail(reason) ` β Errors the stream (sends ` RESET_STREAM ` to peer).
24592470 When ` reason ` is a [ ` QuicError ` ] [ ] , its [ ` error.errorCode ` ] [ ] is used
24602471 as the wire code on the resulting ` RESET_STREAM ` frame; otherwise
@@ -2464,7 +2475,20 @@ The Writer has the following methods:
24642475 See [ ` stream.destroy() ` ] [ ] for a full-stream abort that also resets
24652476 the readable side via ` STOP_SENDING ` .
24662477* ` canWrite ` β ` true ` if writes will be accepted, ` false ` if at capacity,
2467- or ` null ` if closed/errored.
2478+ or ` null ` if closed/errored. When ` writeSync() ` returns ` false ` , use
2479+ ` ondrain() ` from ` node:stream/iter ` to wait before retrying. If ` ondrain() `
2480+ returns ` null ` , no drain wait is available and the write should not be
2481+ retried.
2482+
2483+ ``` mjs
2484+ import { ondrain } from ' node:stream/iter' ;
2485+
2486+ while (! writer .writeSync (chunk)) {
2487+ const drain = ondrain (writer);
2488+ if (drain === null ) break ;
2489+ await drain;
2490+ }
2491+ ```
24682492
24692493The bytes from each ` writeSync() ` / ` writevSync() ` / ` write() ` / ` writev() `
24702494input chunk are copied into an internal buffer, so the caller's source
0 commit comments