如何在node.js中创建可中断循环
免责声明:我是Node.js新手,下面的描述可能会很长 我目前正在尝试自学Node.js,以完成一个小项目。项目理念如下:RaspberryPI运行Node.js应用程序,允许我控制RGB LED条带的颜色。应用程序应该能够设置静态颜色,也可以运行颜色控制盘,以平滑地更改颜色 我现在的想法是创建几个Node.js脚本:如何在node.js中创建可中断循环,node.js,events,asynchronous,Node.js,Events,Asynchronous,免责声明:我是Node.js新手,下面的描述可能会很长 我目前正在尝试自学Node.js,以完成一个小项目。项目理念如下:RaspberryPI运行Node.js应用程序,允许我控制RGB LED条带的颜色。应用程序应该能够设置静态颜色,也可以运行颜色控制盘,以平滑地更改颜色 我现在的想法是创建几个Node.js脚本: 进行客户端通信、设置静态颜色或能够启动色轮的“控制器” “客户端脚本”,每个脚本运行一个色轮。其中最多有一个是“活动的”,由“控制器”启动/停止 我已经能够创建一个小脚本来派生另
子脚本停止该脚本。发送如下所示:
external trigger --> listener ----------> code that changes color
(ie. web client) (ie. web server)
controller.js
var fork = require('child_process').fork,
test2 = fork(__dirname + '/test2.js');
setTimeout(function() { test2.send({func: 'quit'}); }, 5000);
function runLoop()
{
console.log("Hello");
setTimeout(runLoop, 1000);
}
process.on('message', function(m) {
if (m.func === 'quit')
{
process.exit(0);
}
});
setTimeout(runLoop, 1000);
这将分叉test2.js
脚本,并在5秒钟后发送退出test2.js的quit
消息
test2.js
var fork = require('child_process').fork,
test2 = fork(__dirname + '/test2.js');
setTimeout(function() { test2.send({func: 'quit'}); }, 5000);
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条的颜色。上述(当然是较短的计时器值——我这里需要10毫秒)是实现可中断循环的可行方法,还是有更简洁的机制我还不知道?如果您使用的是setTimeout
,您甚至不需要进行新的处理。下面是我将如何编写您的示例:
var ntrvl = setInterval(function() { console.log('Hello'); }, 1000);
setTimeout(function() { clearInterval(ntrvl); }, 5000);
。。。很简单。使用setTimeout
和setInterval
,您使用的是异步函数,因此不会阻塞事件循环。当计时器启动时,它运行您的代码,然后等待下一个事件。您应该能够控制所有的“客户机”,您的带宽将远远超过您实际需要的带宽,所有这些都以这种方式在同一过程中同时进行
你需要注意的是你没有阻止脚本。如果尝试同步执行任何操作(这意味着脚本将在执行下一个命令之前等待操作完成),则需要确保它快速运行。如果您必须同步运行处理器/时间密集型任务,则此时您需要进行新的处理。您正在使生活变得复杂。您的全球架构如下所示:
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);
};
然后,侦听器模块使用颜色变换器
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);
感谢您的回答-我理解虽然分叉可能是“过度的”,但我可以这样做,以确保平滑的色轮不会被控制器所做的事情打断(并保持模块化,我也希望这样做)?只要一切都是正确的异步,那么单线程性能将与您在这里所做的工作无法区分,并且具有作为节点工作方式的“附带好处”。我不知道您实际使用的是什么模块或库与灯光进行交互,因此如果它不是异步的,那么您所做的将是必要的。感谢您向我展示了这种非常优雅的方式。:-)我理解您在这里所做的,在我看来,这个解决方案是一种非常优雅的方式,可以在ColorChanger
类中实现不同的色轮类型。