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.