66

私は現在、nodejs を学習しようとしています。私が取り組んでいる小さなプロジェクトでは、ネットワーク化された LED ライトを制御するための API を作成しています。

LED を制御するマイクロプロセッサには処理遅延があり、少なくとも 100 ミリ秒間隔でマイクロプロセッサにコマンドを送信する必要があります。C# では、Thread.Sleep(time) を呼び出すことに慣れていますが、ノードで同様の機能を見つけられませんでした。

ノードで setTimeout(...) 関数を使用していくつかの解決策を見つけましたが、これは非同期であり、スレッドをブロックしません (これは、このシナリオで必要なものです)。

ブロッキングスリープまたは遅延機能を知っている人はいますか? できれば、CPU を回転させるだけでなく、精度が +-10 ミリ秒のものが望ましいですか?

4

13 に答える 13

71

ノードは本質的に非同期であり、それが優れているため、実際にはスレッドをブロックするべきではありませんが、これは LED を制御するプロジェクトのように思われるため、たとえそれが非常に重要でなくても、とにかくワークアラウンドを投稿します。良いものであり、使用すべきではありません(真剣に)。

while ループはスレッドをブロックするため、独自のスリープ関数を作成できます

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

として使用する

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

Nodeにはブロック機能が組み込まれていないため、スレッドを(原則として)ブロックしてループでビジー状態に保つ唯一の方法だと思います。これは、非同期動作の目的を少し無効にするためです。

于 2014-01-07T08:42:06.297 に答える
41

最善の解決策は、すべてのコマンドをキューに入れ、指定された遅延でそれらを実行する 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();

これで、呼び出すことができLed.exec、すべての遅延が処理されます。

Led.exec(cmd, function() {
  console.log('Command sent');
});
于 2014-01-07T09:36:13.967 に答える
35

Node sleep パッケージを使用します。https://www.npmjs.com/package/sleep .

コードで使用できます

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

特定の n 秒間スリープします。

于 2015-08-28T06:35:26.203 に答える
32

child_process.execSyncシステムのスリープ機能を使用して呼び出すだけです。

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

これをメイン アプリケーション スクリプトの先頭のループで使用して、アプリケーションの残りの部分を実行する前に、ネットワーク ドライブが接続されるまで Node を待機させます。

于 2016-03-12T03:32:03.970 に答える
2

ここでほとんど機能しているものを見つけましたhttps://stackoverflow.com/questions/21819858/how-to-wrap-async-function-calls-into-a-sync-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);`

固有の問題は、印刷された日付が正しくないことですが、少なくともプロセスは連続しています。

于 2016-09-13T08:55:00.013 に答える
2

ネイティブアドオンで実装するのはかなり簡単なので、誰かがそれをしました: https://github.com/ErikDubbelboer/node-sleep.git

于 2014-01-07T11:51:55.207 に答える
1

タイトなハードウェア ソリューションを開発する場合でも、Node.js でのブロックは必要ありません。またはsetImmediateを使用しないtemporal.jsを参照してください。代わりに、より高い解像度のタスク実行を提供するorを使用し、タスクの線形リストを作成できます。ただし、スレッドをブロックせずに実行できます。setTimeoutsetIntervalsetImmediatenextTick

于 2014-12-12T18:43:43.897 に答える
0

sleep パッケージの作成者が示唆しているように* :

function msleep(n) {
  Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, n);
}

function sleep(n) {
  msleep(n * 1000);
}
于 2022-01-19T04:45:07.547 に答える