It is a little bit more tricky than this:
const task = new Promise((resolve, reject) => setTimeout(resolve, 5000, 'done') ) const timeout = new Promise((resolve, reject) => setTimeout(reject, 100, 'timed out') ) Promise .race([ timeout, task ]) .then(console.log) .catch(console.error);
If you run this, you will find out that the process terminates only after both promises are done (i.e. after around 5 seconds):
time node src/race.js timed out node src/race.js 0,36s user 0,03s system 7% cpu 5,370 total
In fact, if one of them is never resolved (and that's exactly what we expect, otherwise we would not introduce a timeout here), the process will hang forever. Seems like `Promise.race` is not doing a proper cleanup. The `task` promise remains pending (event though it's eventual value will never propagate through the chain). This makes the runtime wait for it's resolution before it terminates.
Unfortunately I don't know of any elegant workaround for this. Currently I simply call `process.exit` somewhere down the chain:
Promise .race([ timeout, task ]) .then(console.log) .catch(console.error); .then(process.exit)
In my book it's not an elegant solution.