Wie erstelle ich einen Schlaf/eine Verzögerung in nodejs, der blockiert?

Lesezeit: 8 Minuten

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

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

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

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

  • Klingt für mich so, als ob Sie das falsche Werkzeug für den Job verwenden. Node wurde entwickelt, um zu sein nicht blockieren, wenn Sie eine Art blockierenden Daemon erstellen möchten, sollten Sie sich nach alternativen Technologien umsehen. Genauigkeit von ~ 10 ms in Netzwerkkontexten ist in den meisten Sprachen leicht machbar….

    – Elias Van Ootegem

    7. Januar 2014 um 8:36 Uhr


  • Oder Sie könnten es auf die “Knoten”-Weise tun und den asynchronen Stil verwenden, um Ihre Programmlogik neu zu modellieren.

    – Passant

    7. Januar 2014 um 8:37 Uhr

  • Sind Sie sicher musst du den Thread blockieren? Wenn Sie neu bei nodejs sind, dann ist es vielleicht einfach so, dass Sie es noch nicht gewohnt sind, den Ablauf in asynchronen Begriffen zu denken/entwerfen 🙂 Wie auch immer, hier gibt es ein Schlafpaket: npmjs.org/package/sleep (Echter Schlaf, wo unterstützt, Beschäftigt-Warten auf Fenster)

    – Super

    7. Januar 2014 um 8:56 Uhr

  • Das bedeutet jedoch nicht unbedingt, dass es blockieren muss, es sei denn, setTimeout hat zu viel Overhead. Ich habe gerade einen einfachen Test gemacht: jsapp.us/#s445.js Wenn Sie dies ausführen, erhalten Sie mit setTimeout höchstens 6 ms Verzögerung, während das Blockieren bis zu 39 ms Verzögerung beträgt (die schlimmsten Fälle sind wahrscheinlich darauf zurückzuführen, dass der Server mit anderen Dingen beschäftigt ist, also möglicherweise nicht im OP-Fall). Aber ich stimme zu, dass node.js wahrscheinlich nicht geeignet ist, wenn absolute 100% Präzision und Zuverlässigkeit erforderlich sind.

    – Super

    7. Januar 2014 um 11:26 Uhr


  • Dort sind legitime Fälle, in denen eine blockierende Lösung benötigt wird, beispielsweise beim Debugging: um Verzögerungen zu simulieren und gleichzeitig die volle Kontrolle über die Ausführungsreihenfolge zu behalten. Die Tatsache, dass Node.js keine direkte Lösung bietet (obwohl es möglich wäre), ist ein Defizit von Node, das sollte nicht als Funktion beworben und auch nicht als Entschuldigung dafür verwendet werden, den Fragesteller zu beschuldigen, der eine vernünftige Frage gestellt hat.

    – Marcin Wojnarski

    16. Dezember 2021 um 0:59 Uhr


Benutzer-Avatar
adeneo

Node ist von Natur aus asynchron, und das ist das Tolle daran, also sollten Sie den Thread wirklich nicht blockieren, aber da dies für ein Projekt zu sein scheint, das LEDs steuert, werde ich trotzdem eine Problemumgehung posten, auch wenn es keine sehr ist Gut und sollte nicht verwendet werden (Ernsthaft).

Eine While-Schleife blockiert den Thread, sodass Sie Ihre eigene Sleep-Funktion erstellen können

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

zu verwenden als

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

Ich denke, dies ist die einzige Möglichkeit, den Thread (im Prinzip) zu blockieren und ihn in einer Schleife zu beschäftigen, da Node keine Blockierungsfunktionalität eingebaut hat, da dies den Zweck des asynchronen Verhaltens irgendwie zunichte machen würde.

  • Ich denke, die richtigen Worte sind “sollte niemals verwendet werden”, denn dies ist ein geschäftiges Warten.

    – Bakudan

    7. Januar 2014 um 8:45 Uhr

  • @Bakudan – hängt davon ab, es sollte niemals wirklich für einen Webserver verwendet werden, aber Node wird für viele andere Dinge verwendet, und in diesem Fall steuert das OP LEDs und fragt speziell nach etwas, um den Thread zu blockieren, und dies tut das.

    – adeneo

    7. Januar 2014 um 8:51 Uhr


  • Ich persönlich denke, dass Node.js eine schlafbasierte Blockierung benötigt. Es ist falsch zu behaupten, dass der/die Autor(en) von Node alle Szenarien kannten. Was ist, wenn Sie Ihre Aktivitäten verlangsamen müssen, damit Sie die Server und Ressourcen anderer Personen nicht überlasten? Es ist eine schlechte Netiquette, den E-Mail-Server eines anderen zu strapazieren, nur weil Sie eine Million ausgehende E-Mails zu senden haben und Ihre bevorzugte Plattform anscheinend keine Verzögerungen zulässt. Danke, Adeneo.

    – Michael Blankenship

    9. Mai 2015 um 21:53 Uhr

  • Es gibt einige npm-Module verfügbar, um eine schlafbasierte Blockierung durchzuführen.

    – Timotheus Gu

    23. Mai 2015 um 1:16 Uhr

  • Und die meisten dieser Module werden geschrieben, nachdem diese Antwort veröffentlicht wurde, und verwenden genau dieselbe Technik.

    – adeneo

    31. Juli 2015 um 22:41 Uhr

Benutzer-Avatar
Leonid Beschastny

Die beste Lösung besteht darin, einen Singleton-Controller für Ihre LED zu erstellen, der alle Befehle in die 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 anrufen Led.exec und es wird alle Verzögerungen für Sie handhaben:

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

  • Ich kann nicht glauben, dass einfache Dinge in NodeJS so kompliziert sind. Gott segne C# und/oder Java!

    – TriCore

    1. Mai 2018 um 2:04 Uhr

  • @TriCore hoffentlich unterstützt NodeJS ES6 und async/await jetzt. Timeouts und asynchrone Operationen sind also nicht mehr so ​​kompliziert.

    – Leonid Beschastny

    1. Mai 2018 um 11:32 Uhr

  • @TriCore God bless Node dafür, dass er dumme Dinge so kompliziert gemacht hat, weil das Blockieren eines einzelnen Threads definitiv dumm ist (dies gilt nicht für die Antwort, die technisch falsch ist, weil sie nicht blockiert). @LeonidBeschastny Eigentlich Generatoren und co bestand zum Zeitpunkt der Fragestellung. Zur Zeit async..await ist sicherlich ein Weg zu gehen.

    – Estus-Kolben

    22. Januar 2019 um 23:04 Uhr


  • ReferenceError: sendCmdToLed ist nicht definiert

    – Jortega

    21. September 2020 um 15:54 Uhr

Benutzer-Avatar
HRJ

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

  • Dies ist die praktischste Schlafform für Bewerbungen. Die Leute sollten jedoch verstehen, dass dies nicht dasselbe ist wie der Sleep-Systemaufruf (alias Thread.sleep()) und der Vertrag darin besteht, dass Sie die App in den Ruhezustand versetzen wenigstens der angegebene Betrag plus die Zeit, die der Rückruf in der Ereigniswarteschlange wartet (normalerweise weniger als 10 ms).

    – Elias Toivanen

    14. Dezember 2021 um 18:09 Uhr


  • Diese Funktion ist nicht blockierendwährend die Frage ausdrücklich nach a fragt Blockierung Lösung.

    – Marcin Wojnarski

    16. Dezember 2021 um 0:28 Uhr

  • Das ist fantastisch! HRJ, Sie haben mir geholfen, nachdem Sie es frustrierend nicht geschafft haben, dies zum Laufen zu bringen. (Ich bin neu in Typoskript)

    – Sander Bouwhuis

    2. Juni um 7:26

Verwenden Sie das Node-Sleep-Paket. https://www.npmjs.com/package/sleep.

in Ihrem Code können Sie verwenden

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

für bestimmte n Sekunden zu schlafen.

Benutzer-Avatar
sffc

Benutz 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 am Anfang meines Hauptanwendungsskripts, damit Node wartet, bis Netzlaufwerke verbunden sind, bevor der Rest der Anwendung ausgeführt wird.

  • child_process.execSync(“sleep 1”); ^ ReferenceError: child_process ist nicht definiert

    – saftig

    16. August 2017 um 9:55 Uhr

  • @sapy Sie müssen das Modul child_process einschließen. Zum Beispiel, const child_process = require("child_process");

    – sffc

    17. August 2017 um 22:16 Uhr

Am einfachsten echte Synchronisierung Lösung (dh kein Yield / Async), die ich mir einfallen lassen könnte, die in allen Betriebssystemen ohne Abhängigkeiten funktioniert, besteht darin, den Knotenprozess aufzurufen, um eine Inline zu evaluieren setTimeout Ausdruck:

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

  • child_process.execSync(“sleep 1”); ^ ReferenceError: child_process ist nicht definiert

    – saftig

    16. August 2017 um 9:55 Uhr

  • @sapy Sie müssen das Modul child_process einschließen. Zum Beispiel, const child_process = require("child_process");

    – sffc

    17. August 2017 um 22:16 Uhr

Benutzer-Avatar
wkurtschatkin

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

  • Dies ist hauptsächlich für Debugging-Zwecke oder zum Schreiben von Tests nützlich. Es ist eine sehr schlechte Idee, den Sperrschlaf in der Produktion zu verwenden.

    – Leonid Beschastny

    7. Januar 2014 um 12:36 Uhr


  • sicher ist es das in den meisten Fällen. aber «Produktion» ist ein weit gefasster Begriff. Wenn Sie keine Kunden bedienen müssen, können Sie Dinge blockieren.

    – wkurtschatkin

    7. Januar 2014 um 13:17 Uhr

  • Es ist in Ordnung, wenn Sie wissen, was Sie tun, js ist nicht nur für Client-Server-Apps.

    – setec

    17. Oktober 2014 um 9:09 Uhr

  • Wenn „Produktion“ eine Reihe von Befehlszeilentools ist, die Administratoren verwenden können (in Knoten geschrieben, um Protokoll-/Client-Code aus der Hauptcodebasis zu verwenden), dann ist das Fehlen von synchronen/blockierenden Dingen in Knoten eine totale PITA … Async Zeug ist in einigen Fällen eine “sehr schlechte Idee in der Produktion”, angesichts der erforderlichen zusätzlichen Tests …

    – Mark K. Cowan

    20. November 2016 um 23:31 Uhr

  • Dies sollte die akzeptierte Lösung sein! der einzige, der die Ereignisschleife tatsächlich blockiert.

    – Bamieh

    31. Juli 2017 um 8:08 Uhr

1066230cookie-checkWie erstelle ich einen Schlaf/eine Verzögerung in nodejs, der blockiert?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy