Skip to content

Commit f6adebd

Browse files
net: use throwIfAborted and improve server iteration example
Address review feedback on the net/promises API: - Use `signal.throwIfAborted()` for the pre-connect and pre-listen abort checks instead of constructing an AbortError by hand. - Update the `server[Symbol.asyncIterator]()` documentation example to dispatch each connection to a separate async task, with a note that awaiting inline serializes connections. Refs: #21482 Assisted-by: Claude Opus 4.8 <noreply@anthropic.com> Signed-off-by: Ethan Arrowood <ethan@arrowood.dev>
1 parent 9885d70 commit f6adebd

2 files changed

Lines changed: 20 additions & 14 deletions

File tree

doc/api/net.md

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -463,18 +463,31 @@ to be consumed with `for await...of` as an alternative to the [`'connection'`][]
463463
event. Iteration ends when the server emits [`'close'`][], and rejects if the
464464
server emits [`'error'`][].
465465

466+
The loop only advances to the next connection once the current iteration's body
467+
has finished awaiting, so connection handling should be dispatched to a separate
468+
async task rather than awaited inline. Otherwise connections are serialized:
469+
each one waits for the previous to be fully handled.
470+
466471
```mjs
467472
import { createServer } from 'node:net';
468473

469474
const server = createServer().listen(8124);
470-
for await (const socket of server) {
475+
476+
async function handleConnection(socket) {
477+
// ...handle the connection, awaiting as needed.
471478
socket.end('hello world!');
472479
}
480+
481+
for await (const socket of server) {
482+
// Dispatch handling to a separate task so the loop keeps accepting
483+
// connections instead of serializing them.
484+
handleConnection(socket);
485+
}
473486
```
474487

475-
Connections are buffered while the loop body is busy; the server does not stop
476-
accepting them, so a consumer that is slower than the connection rate can buffer
477-
without bound. Use [`server.maxConnections`][] to bound concurrency.
488+
The server does not stop accepting connections while the loop body runs, so a
489+
consumer slower than the connection rate can buffer them without bound. Use
490+
[`server.maxConnections`][] to bound concurrency.
478491

479492
### `server.getConnections(callback)`
480493

@@ -2186,9 +2199,7 @@ with `for await...of` (see `server[Symbol.asyncIterator]()`).
21862199
import { listen } from 'node:net/promises';
21872200

21882201
const server = await listen({ port: 8124 });
2189-
for await (const socket of server) {
2190-
socket.end('hello world!');
2191-
}
2202+
console.log('listening on', server.address().port);
21922203
```
21932204

21942205
[IPC]: #ipc-support

lib/internal/net/promises.js

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ const {
55
validateAbortSignal,
66
validateObject,
77
} = require('internal/validators');
8-
const { AbortError } = require('internal/errors');
98
const { kEmptyObject } = require('internal/util');
109

1110
// Lazily loaded to avoid a require cycle with the `net` module, which exposes
@@ -24,9 +23,7 @@ async function connect(...args) {
2423
const { signal } = options;
2524
if (signal !== undefined) {
2625
validateAbortSignal(signal, 'options.signal');
27-
if (signal.aborted) {
28-
throw new AbortError(undefined, { cause: signal.reason });
29-
}
26+
signal.throwIfAborted();
3027
}
3128

3229
// Strip the signal so the socket does not also install its own abort
@@ -49,9 +46,7 @@ async function listen(options = kEmptyObject) {
4946
const { signal, connectionListener } = options;
5047
if (signal !== undefined) {
5148
validateAbortSignal(signal, 'options.signal');
52-
if (signal.aborted) {
53-
throw new AbortError(undefined, { cause: signal.reason });
54-
}
49+
signal.throwIfAborted();
5550
}
5651

5752
const lazy = lazyNet();

0 commit comments

Comments
 (0)