Is it possible to use setTimeout in NodeJS to terminate a process even if the event loop is being occupied by something else?
For example, say I have code that looks like the following
setTimeout(async () => {
// Some code I run to gracefully exit my process.
}, timeout);
while (true) {
let r = 1;
}
The callback in my timeout will never be hit since the while loop will occupy the event loop. Is there some way that I can say: "Execute the following code after N seconds regardless of everything else?"
I'm writing selenium tests, but for some reason every once in a while the test will get "stuck" and never terminate. I basically want to always timeout my tests after a certain amount of time so we don't get into the position of tests that run forever.
Thanks!
Since JavaScript is single threaded, what you are going to want to do is to create a worker using fork, which will give it the feeling of being multi threaded. This will actually just give us two instances of node, each one having their own event loop. This fork will have your endless loop which you can then kill with your timeout.
main.js
const cp = require('child_process')
const path = require('path')
// Create the child
const child = cp.fork(path.join(__dirname, './worker.js'), [])
// Kill after "x" milliseconds
setTimeout(() => {
process.exit()
}, 5000);
// Listen for messages from the child
child.on('message', data => console.log(data))
Next you will setup your worker:
worker.js
let i = 0;
while (true) {
// Send the value of "i" to the parent
process.send(i++);
}
The child can communicate info about itself to the parent using process.send(data)
.
The parent can listen for messages from the child using child.on('message', ...)
.
Another thing we can do is kill the child instead of the main process if you need the main process to do more stuff still. And in this case you would call child.kill()
inside the setTimeout
instead.
const cp = require('child_process')
const path = require('path')
// Create the child
let child = cp.fork(path.join(__dirname, './worker.js'), [])
// Kill after "x" milliseconds
setTimeout(() => {
child.kill()
}, 5000);
If there are no more events in the eventloop, the main process will automatically close itself thus we don't need to call process.exit()
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With