How to create a sleep/delay in nodejs that is Blocking?
Solution 1:
Node is asynchronous by nature, and that's what's great about it, so you really shouldn't be blocking the thread, but as this seems to be for a project controlling LED's, I'll post a workaraound anyway, even if it's not a very good one and shouldn't be used (seriously).
A while loop will block the thread, so you can create your own sleep function
function sleep(time, callback) {
var stop = new Date().getTime();
while(new Date().getTime() < stop + time) {
;
}
callback();
}
to be used as
sleep(1000, function() {
// executes after one second, and blocks the thread
});
I think this is the only way to block the thread (in principle), keeping it busy in a loop, as Node doesn't have any blocking functionality built in, as it would sorta defeat the purpose of the async behaviour.
Solution 2:
With ECMA script 2017 (supported by Node 7.6 and above), it becomes a one-liner:
function sleep(millis) {
return new Promise(resolve => setTimeout(resolve, millis));
}
// Usage in async function
async function test() {
await sleep(1000)
console.log("one second has elapsed")
}
// Usage in normal function
function test2() {
sleep(1000).then(() => {
console.log("one second has elapsed")
});
}
Solution 3:
The best solution is to create singleton controller for your LED which will queue all commands and execute them with specified delay:
function LedController(timeout) {
this.timeout = timeout || 100;
this.queue = [];
this.ready = true;
}
LedController.prototype.send = function(cmd, callback) {
sendCmdToLed(cmd);
if (callback) callback();
// or simply `sendCmdToLed(cmd, callback)` if sendCmdToLed is async
};
LedController.prototype.exec = function() {
this.queue.push(arguments);
this.process();
};
LedController.prototype.process = function() {
if (this.queue.length === 0) return;
if (!this.ready) return;
var self = this;
this.ready = false;
this.send.apply(this, this.queue.shift());
setTimeout(function () {
self.ready = true;
self.process();
}, this.timeout);
};
var Led = new LedController();
Now you can call Led.exec
and it'll handle all delays for you:
Led.exec(cmd, function() {
console.log('Command sent');
});
Solution 4:
use Node sleep package. https://www.npmjs.com/package/sleep.
in your code you can use
var sleep = require('sleep');
sleep.sleep(n)
to sleep for a specific n seconds.
Solution 5:
Just use child_process.execSync
and call the system's sleep function.
//import child_process module
const child_process = require("child_process");
// Sleep for 5 seconds
child_process.execSync("sleep 5");
// Sleep for 250 microseconds
child_process.execSync("usleep 250");
// Sleep for a variable number of microseconds
var numMicroSeconds = 250;
child_process.execFileSync("usleep", [numMicroSeconds]);
I use this in a loop at the top of my main application script to make Node wait until network drives are attached before running the rest of the application.