如何在node.js中创建可中断循环

如何在node.js中创建可中断循环,node.js,events,asynchronous,Node.js,Events,Asynchronous,免责声明:我是Node.js新手,下面的描述可能会很长 我目前正在尝试自学Node.js,以完成一个小项目。项目理念如下:RaspberryPI运行Node.js应用程序,允许我控制RGB LED条带的颜色。应用程序应该能够设置静态颜色,也可以运行颜色控制盘,以平滑地更改颜色 我现在的想法是创建几个Node.js脚本: 进行客户端通信、设置静态颜色或能够启动色轮的“控制器” “客户端脚本”,每个脚本运行一个色轮。其中最多有一个是“活动的”,由“控制器”启动/停止 我已经能够创建一个小脚本来派生另

免责声明:我是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
    类中实现不同的色轮类型。