2014-01-28 81 views
2
可中斷循環

免責聲明:我是一個新手的Node.js和下面的描述會很長......如何創建node.js中

我目前正試圖教自己Node.js加載了我追求的小項目。項目的想法如下:RaspberryPI運行Node.js應用程序,該應用程序允許我控制RGB LED燈條的顏色。應用程序應該能夠設置一個靜態顏色,並且還可以運行平滑改變顏色的色輪。

我的想法是,現在創建幾個Node.js的腳本:

  1. 「控制器」,做客戶的溝通,設置靜態顏色或者是能夠啓動的色輪
  2. 「客戶端腳本」每個運行一個色輪。在大多數人會是「活着」,開始/由「控制器」

我已經能夠創建一個小腳本叉另一個腳本,並能夠如下停止使用child.send該腳本停止:

controller.js

var fork = require('child_process').fork, 
    test2 = fork(__dirname + '/test2.js'); 

setTimeout(function() { test2.send({func: 'quit'}); }, 5000); 

這叉test2.js腳本和5秒後發送quit消息退出test2.js

test2.js

function runLoop() 
{ 
    console.log("Hello"); 
    setTimeout(runLoop, 1000); 
} 

process.on('message', function(m) { 
    if (m.func === 'quit') 
    { 
    process.exit(0); 
    } 
}); 

setTimeout(runLoop, 1000); 

這種 「客戶端腳本」 打印 「Hello」 每秒直到控制器發送quit消息。

這很有效 - 5秒鐘後腳本正常完成。

我現在的問題是:如果我實現了一個色輪,我需要一個可能無限循環來改變LED燈條的顏色。上面的(當然有更短的定時器值 - 我需要10ms這樣的東西)是實現可中斷循環的一種可行的方式,還是存在一些我還不知道的整潔機制?

回答

1

你讓生活變得複雜。您的全球架構如下:

external trigger --> listener ----------> code that changes color 
(ie. web client)  (ie. web server) 

考慮到這一點,你不需要任何叉的過程,你可以在一個過程中控制LED燈帶。某處在你的代碼,就必須與此類似的對象:

//"led" is the module that allows you to change the color of a led (suppose 4 leds) 
var led = require ("led-controller"); 

var ColorChanger = module.exports = function(){ 
    this._intervalId = null; 
}; 

ColorChanger.prototype.setColor = function (hex){ 
    //Color in hexadecimal 

    //Cancel any current interval 
    cancelInterval (this._intervalId); 

    led.color (0, hex); 
    led.color (1, hex); 
    led.color (2, hex); 
    led.color (3, hex); 
}; 

ColorChanger.prototype.wheel = function (hex, ms){ 
    //Color in hexadecimal 
    //"ms" is the time interval between leds going on and off 

    //Cancel any current interval 
    cancelInterval (this._intervalId); 

    //Shutdown all the leds 
    led.off (0); 
    led.off (1); 
    led.off (2); 
    led.off (3); 

    //Activate the first led 
    led.color (0, hex); 

    //Current active led 
    var curr = 0; 

    this._intervalId = setInterval (function(){ 
     //Each "ms" the current led will go off and the next will go on 
     led.off (curr); 
     //Next led to activate 
     curr = ++curr%4; 
     led.color (curr, hex); 
    }, ms); 
}; 

然後監聽模塊使用ColorChanger

var ColorChanger = require ("./color-changer"); 

var changer = new ColorChanger(); 

//Set all the leds to red 
changer.setColor ("#FF0000"); 

//Each 10ms one led goes green and the previous is turned off, in an endless loop 
changer.wheel ("#00FF00", 10); 
+0

感謝您向我展示這種相當優雅的做事方式。 :-)我明白你在做什麼,這個解決方案對我來說就像是在ColorChanger類中實現不同色輪類型的一種非常優雅的方式。 –

2

如果您使用的是setTimeout,您甚至不需要分叉新的進程。下面是我將如何寫你的例子:

var ntrvl = setInterval(function() { console.log('Hello'); }, 1000); 
setTimeout(function() { clearInterval(ntrvl); }, 5000); 

...很簡單。使用setTimeoutsetInterval,您使用的是異步函數,因此您不會阻止事件循環。當計時器啓動時,它會運行您的代碼,然後等待下一個事件。您應該能夠控制所有的「客戶端」,您將擁有比您實際需要的帶寬更多的帶寬,並且同時以相同的流程完成。

所有你需要警惕的是,你沒有阻止腳本。如果您嘗試同步執行任何操作(這意味着腳本將在執行下一個命令之前等待操作完成),那麼您需要確保它快速運行。如果您必須同步運行處理器/時間密集型任務,那麼您需要分叉一個新進程。

+0

謝謝你這個答案 - 我明白,雖然分叉可能是「潔癖」在這裏,我*可能*做到這一點,以確保順利色輪不是由什麼控制器是做中斷(和保持事物模塊化,我也想這樣做)? –

+0

只要一切都正確異步,那麼單線程性能就不會與你在這裏做的事情區分開來,並且具有作爲節點工作方式的「副作用」。我不知道你用什麼模塊或庫實際上與燈互動,所以如果它不是異步的,那麼你需要做的是什麼。 – Jason

相關問題