it-swarm.com.de

Wie erstelle ich einen sleep/delay in nodejs, der blockiert?

Ich versuche gerade, nodejs zu lernen, und ein kleines Projekt, an dem ich arbeite, schreibt eine API zur Steuerung einiger vernetzter LED-Leuchten.

Der Mikroprozessor, der die LEDs steuert, hat eine Verarbeitungsverzögerung, und ich muss Befehle an das Mikro senden, die mindestens 100 ms voneinander entfernt sind. In C # bin ich es gewohnt, nur Thread.Sleep (Zeit) aufzurufen, aber ich habe keine ähnliche Funktion im Knoten gefunden.

Ich habe mehrere Lösungen gefunden, die die Funktion setTimeout (...) im Knoten verwenden. Dies ist jedoch asynchron und blockiert den Thread nicht (was ich in diesem Szenario brauche).

Kennt jemand eine blockierende Schlaf- oder Verzögerungsfunktion? Vorzugsweise etwas, das nicht nur die CPU dreht, und eine Genauigkeit von + -10 ms hat?

45
on3al

Die beste Lösung ist, einen Einzelsteuerpult für Ihre LED zu erstellen, der alle Befehle in eine Warteschlange stellt und sie mit einer bestimmten Verzögerung ausführt:

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();

Jetzt können Sie Led.exec aufrufen, und es werden alle Verzögerungen für Sie erledigt:

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

Node ist von Natur aus asynchron, und das ist das Tolle daran, also sollte man den Thread wirklich nicht blockieren, aber da dies für ein Projekt zu sein scheint, das LEDs steuert, schreibe ich sowieso einen Workaraound, auch wenn es nicht sehr ist Gutes und sollte nicht verwendet werden (ernsthaft).

Eine while-Schleife blockiert den Thread, sodass Sie Ihre eigene Schlaffunktion erstellen können

function sleep(time, callback) {
    var stop = new Date().getTime();
    while(new Date().getTime() < stop + time) {
        ;
    }
    callback();
}

verwendet werden als

sleep(1000, function() {
   // executes after one second, and blocks the thread
});

Ich denke, dass dies der einzige Weg ist, den Thread (im Prinzip) zu blockieren und ihn in einer Schleife zu beschäftigen, da Node keine eingebauten Blockierungsfunktionen enthält, da dies den Zweck des asynchronen Verhaltens zerstören würde.

56
adeneo

node Sleep-Paket verwenden. https://www.npmjs.com/package/sleep .

in Ihrem Code können Sie verwenden 

var sleep = require('sleep'); 
sleep.sleep(n)

n Sekunden lang schlafen.

26
Manoj Sanjeewa

Verwenden Sie einfach child_process.execSync und rufen Sie die Sleep-Funktion des Systems auf.

//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]);

Ich verwende dies in einer Schleife oben in meinem Hauptanwendungsskript, um Node warten zu lassen, bis Netzlaufwerke angeschlossen sind, bevor der Rest der Anwendung ausgeführt wird.

17
sffc

Mit dem ECMA-Skript 2017 (unterstützt von Node 7.6 und höher) wird es zu einem Einzeiler:

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")
  });
}
3
HRJ

Es ist ziemlich trivial mit einem nativen Addon zu implementieren, also hat jemand das getan: https://github.com/ErikDubbelboer/node-sleep.git

2
vkurchatkin

Ich habe etwas gefunden, das fast funktioniert hier https://stackoverflow.com/questions/21819858/how-to-wrap-async-function-calls-into-async-function-in-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);`

Das eindeutige Problem ist, dass das Datum nicht gedruckt wurde, der Prozess jedoch zumindest sequenziell ist.

2
Alex

Einfachste True Sync Lösung (d. H. Kein Ertrag/Async) Ich könnte mir vorstellen, dass es in allen Betriebssystemen ohne Abhängigkeiten funktioniert, den Knotenprozess aufzurufen, um einen Inline-Ausdruck setTimeout auszuwerten:

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

Das Sperren in Node.js ist selbst bei der Entwicklung enger Hardwarelösungen nicht erforderlich. Siehe temporal.js , das setTimeout oder setIntervalsetImmediate nicht verwendet. Stattdessen werden setImmediate oder nextTick verwendet, was die Ausführung von Aufgaben mit einer höheren Auflösung ermöglicht und Sie können eine lineare Liste von Aufgaben erstellen. Sie können dies jedoch tun, ohne den Thread zu blockieren.

1
Brian Genisio

Sie können einfach die yield-Funktion verwenden, die in der ECMA6- und gen-run-Bibliothek eingeführt wurde:

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!");
});
0
NaWeeD