如何在阻塞的node . js中创建一个睡眠/延迟?

时间:2022-04-20 20:56:26

I'm currently trying to learn nodejs and a small project I'm working is writing an API to control some networked LED lights.

我目前正在努力学习nodejs和一个我正在工作的小项目是编写一个API来控制一些联网的LED灯。

The microprocessor controlling the LEDs has a processing delay, and I need to space commands sent to the micro at least 100ms apart. In C# I'm used to just calling Thread.Sleep(time), but I have not found a similar feature in node.

控制led的微处理器有一个处理延迟,我需要将发送给微处理器的命令间隔至少100ms。在c#中,我习惯了只调用Thread.Sleep(time),但是我在node中没有发现类似的特性。

I have found several solutions using the setTimeout(...) function in node, however, this is asynchronous and does not block the thread ( which is what I need in this scenario).

我在node中使用setTimeout(…)函数找到了几个解决方案,但是,这是异步的,不会阻塞线程(这是我在这个场景中需要的)。

Is anyone aware of a blocking sleep or delay function? Preferably something that does not just spin the CPU, and has an accuracy of +-10 ms?

有没有人意识到睡眠或延迟的功能?最好是不只是旋转CPU,并且精度为+- 10ms的?

10 个解决方案

#1


36  

The best solution is to create singleton controller for your LED which will queue all commands and execute them with specified delay:

最好的解决方案是为您的LED创建单例控制器,该控制器将对所有命令进行排队,并以指定的延迟执行它们:

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。它将为您处理所有的延迟:

Led.exec(cmd, function() {
  console.log('Command sent');
});

#2


54  

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).

Node本质上是异步的,这就是它的优点所在,所以您确实不应该阻塞线程,但是由于这似乎是一个控制LED的项目,所以无论如何,我将发布一个workaraound,即使它不是一个很好的,也不应该(认真地)使用它。

A while loop will block the thread, so you can create your own sleep function

while循环将阻塞线程,因此您可以创建自己的sleep函数

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.

我认为这是阻塞线程的唯一方法(原则上),使它在循环中保持忙碌,因为Node没有任何内置的阻塞功能,因为它会破坏异步行为的目的。

#3


20  

use Node sleep package. https://www.npmjs.com/package/sleep.

使用节点睡眠包。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.

睡上特定的n秒。

#4


15  

Just use child_process.execSync and call the system's sleep function.

只使用child_process。执行并调用系统的睡眠功能。

//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.

我在主应用程序脚本顶部的一个循环中使用这个,使节点等待直到网络驱动器在运行其余应用程序之前连接。

#5


2  

I found something almost working here https://*.com/questions/21819858/how-to-wrap-async-function-calls-into-a-sync-function-in-node-js-or-ja vascript

我在这里发现了一些几乎可以工作的东西:https://*.com/questions/21819858/how-to-异步-函数-调用-in- to- sync- sync- functionin node-js-or-ja vascript

`function AnticipatedSyncFunction(){
    var ret;
    setTimeout(function(){
        var startdate = new Date()
        ret = "hello" + startdate;
    },3000);
    while(ret === undefined) {
       require('deasync').runLoopOnce();
    }
    return ret;    
}


var output = AnticipatedSyncFunction();
var startdate = new Date()
console.log(startdate)
console.log("output="+output);`

The unique problem is the date printed isn't correct but the process at least is sequential.

唯一的问题是打印的日期不正确,但过程至少是连续的。

#6


2  

Blocking in Node.js is not necessary, even when developing tight hardware solutions. See temporal.js which does not use setTimeout or setIntervalsetImmediate. Instead, it uses setImmediate or nextTick which give much higher resolution task execution, and you can create a linear list of tasks. But you can do it without blocking the thread.

在节点阻塞。js不是必需的,即使在开发紧密的硬件解决方案时也是如此。看时间。不使用setTimeout或setintervalsetimmediation的js。相反,它使用setimmediation或nextTick来提供更高分辨率的任务执行,您可以创建任务的线性列表。但是你可以在不阻塞线程的情况下做到这一点。

#7


1  

It's pretty trivial to implement with native addon, so someone did that: https://github.com/ErikDubbelboer/node-sleep.git

使用本机addon实现非常简单,所以有人这样做了:https://github.com/erikdubbelboer/nodesleep.git。

#8


0  

You can simply use yield feature introduced in ECMA6 and gen-run library:

您可以简单地使用ECMA6和gen-run库中引入的yield特性:

let run = require('gen-run');


function sleep(time) {
    return function (callback) {
        setTimeout(function(){
            console.log(time);
            callback();
        }, time);
    }
}


run(function*(){
    console.log("befor sleeping!");
    yield sleep(2000);
    console.log("after sleeping!");
});

#9


0  

Easiest true sync solution (i.e. no yield/async) I could come up with that works in all OS's without any dependencies is to call the node process to eval an in-line setTimeout expression:

最简单的真正的同步解决方案(即no yield/async),我可以在所有操作系统的无依赖项中找到工作,将节点进程称为eval的in-line setTimeout表达式:

const sleep = (ms) => require("child_process")
    .execSync(`"${process.argv[0]}" -e setTimeout(function(){},${ms})`);

#10


-2  

blocking the main thread is not a good style for node because in most cases more then one person is using it. You should use settimeout/setinterval in combination with callbacks.

对node来说,阻塞主线程不是一种很好的样式,因为在大多数情况下,更多的人在使用它。您应该结合使用settimeout/setinterval和回调。

#1


36  

The best solution is to create singleton controller for your LED which will queue all commands and execute them with specified delay:

最好的解决方案是为您的LED创建单例控制器,该控制器将对所有命令进行排队,并以指定的延迟执行它们:

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。它将为您处理所有的延迟:

Led.exec(cmd, function() {
  console.log('Command sent');
});

#2


54  

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).

Node本质上是异步的,这就是它的优点所在,所以您确实不应该阻塞线程,但是由于这似乎是一个控制LED的项目,所以无论如何,我将发布一个workaraound,即使它不是一个很好的,也不应该(认真地)使用它。

A while loop will block the thread, so you can create your own sleep function

while循环将阻塞线程,因此您可以创建自己的sleep函数

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.

我认为这是阻塞线程的唯一方法(原则上),使它在循环中保持忙碌,因为Node没有任何内置的阻塞功能,因为它会破坏异步行为的目的。

#3


20  

use Node sleep package. https://www.npmjs.com/package/sleep.

使用节点睡眠包。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.

睡上特定的n秒。

#4


15  

Just use child_process.execSync and call the system's sleep function.

只使用child_process。执行并调用系统的睡眠功能。

//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.

我在主应用程序脚本顶部的一个循环中使用这个,使节点等待直到网络驱动器在运行其余应用程序之前连接。

#5


2  

I found something almost working here https://*.com/questions/21819858/how-to-wrap-async-function-calls-into-a-sync-function-in-node-js-or-ja vascript

我在这里发现了一些几乎可以工作的东西:https://*.com/questions/21819858/how-to-异步-函数-调用-in- to- sync- sync- functionin node-js-or-ja vascript

`function AnticipatedSyncFunction(){
    var ret;
    setTimeout(function(){
        var startdate = new Date()
        ret = "hello" + startdate;
    },3000);
    while(ret === undefined) {
       require('deasync').runLoopOnce();
    }
    return ret;    
}


var output = AnticipatedSyncFunction();
var startdate = new Date()
console.log(startdate)
console.log("output="+output);`

The unique problem is the date printed isn't correct but the process at least is sequential.

唯一的问题是打印的日期不正确,但过程至少是连续的。

#6


2  

Blocking in Node.js is not necessary, even when developing tight hardware solutions. See temporal.js which does not use setTimeout or setIntervalsetImmediate. Instead, it uses setImmediate or nextTick which give much higher resolution task execution, and you can create a linear list of tasks. But you can do it without blocking the thread.

在节点阻塞。js不是必需的,即使在开发紧密的硬件解决方案时也是如此。看时间。不使用setTimeout或setintervalsetimmediation的js。相反,它使用setimmediation或nextTick来提供更高分辨率的任务执行,您可以创建任务的线性列表。但是你可以在不阻塞线程的情况下做到这一点。

#7


1  

It's pretty trivial to implement with native addon, so someone did that: https://github.com/ErikDubbelboer/node-sleep.git

使用本机addon实现非常简单,所以有人这样做了:https://github.com/erikdubbelboer/nodesleep.git。

#8


0  

You can simply use yield feature introduced in ECMA6 and gen-run library:

您可以简单地使用ECMA6和gen-run库中引入的yield特性:

let run = require('gen-run');


function sleep(time) {
    return function (callback) {
        setTimeout(function(){
            console.log(time);
            callback();
        }, time);
    }
}


run(function*(){
    console.log("befor sleeping!");
    yield sleep(2000);
    console.log("after sleeping!");
});

#9


0  

Easiest true sync solution (i.e. no yield/async) I could come up with that works in all OS's without any dependencies is to call the node process to eval an in-line setTimeout expression:

最简单的真正的同步解决方案(即no yield/async),我可以在所有操作系统的无依赖项中找到工作,将节点进程称为eval的in-line setTimeout表达式:

const sleep = (ms) => require("child_process")
    .execSync(`"${process.argv[0]}" -e setTimeout(function(){},${ms})`);

#10


-2  

blocking the main thread is not a good style for node because in most cases more then one person is using it. You should use settimeout/setinterval in combination with callbacks.

对node来说,阻塞主线程不是一种很好的样式,因为在大多数情况下,更多的人在使用它。您应该结合使用settimeout/setinterval和回调。