Hacker News new | ask | show | jobs
by molsson 612 days ago
process.stdout._handle.setBlocking(true)

...is a bit brutal but works. Draining the stream before exiting also kind of works but there are cases where drain will just permanently block.

async function drain(stream) { return new Promise((resolve) => stream.on('drain', resolve)) }

2 comments

When you want to await a single instance of a Node EventEmitter, please use `stream.once('drain', (err) => ...)` so you don't leak your listener callback after the promise resolves.
Which cases will it permanently block?
The writable stream will only emit 'drain' if the buffer fills past the limit. In that case, a prior call to `writable.write(...)` would return `false` indicating you should wait for drain before calling write again. Even if your code can't access the return value for the last writable.write call, you can check `if (writable.writableNeedDrain) { ...` to decide to wait for drain.

This program will run forever, since we never write to stdout, stdout never "drains":

    setInterval(() => console.error("stderr: ", new Date().toISOString()), 5_000)
    process.stdout.once("drain", () => {
      console.error("stderr: stdout.once.drain, exit")
      process.exit(0)
    })