不断检查对象值,如果错误则结束处理

时间:2018-08-10 13:12:24

标签: javascript node.js events

我正在为树莓派上带有Node的机器构建一个控制系统。如果其中一个安全继电器断开,则某些过程需要立即停止。因此,我需要每隔100ms id检查一次安全继电器是否打开,如果打开,则发送信号以停止运行某些功能。

通常,如果Relays.allClosed为假,将需要停止几个功能。

var Relays = {
  relay1: false,
  relay2: false,
  allClosed: false,
  checkRelays: function() {
    if (this.relay1 == true && this.relay2 == true) {
      this.allClosed = true
    } else {
      this.allClosed = false
      console.warn("relay open")
    }
  }
}

var safetyCheck = function() { //checks if safety relays are all closed every 100 ms
  setInterval(function() {
    Relays.checkRelays()
  }, 100)
}

safetyCheck()

Machine.run = function(distance) {
  if (Relays.allClosed) { //checks before running the process if the relays are all closed for safety
    // if at any point while running this Relays.allClosed becomes false, function needs to stop running
    setTimeout(function() {
      console.log('advancing press');
      i++;
      if (i < distance) {
        pressLoop();
      }
    }, 1000)
  } else {
    console.log("can't run machine because one or more safety relay is open")
  }
}

2 个答案:

答案 0 :(得分:0)

当发生有意义的事情时,您应该使用EventEmitter之类的东西来发出事件。这可能是您的allClosed值的状态变化(尽管我认为您不断轮询变化的中继状态的方法是一种反模式,并且应该始终使用基于事件的逻辑)。 / p>

但是在任何情况下,假设引发allClosed事件,您都可以捕获该事件并停止运行的代码:

Machine.run = function(distance) {
  if (Relays.allClosed) { //checks before running the process if the relays are all closed for safety
    // if at any point while running this Relays.allClosed becomes false, function needs to stop running
    let timer = setTimeout(function() {
      console.log('advancing press');
      i++;
      if (i < distance) {
        pressLoop();
      }
    }, 1000);

    myEventEmitter.on("allClosed", () => {
       clearTimeout(timer);
    })
  } else {
    console.log("can't run machine because one or more safety relay is open")
  }
}

此操作将在下一次迭代时取消,但是如果pressLoop以某种方式长时间运行,则也应准备中途停止该操作。


以下代码说明了(用按钮代替物理继电器)如何运行整个事件一系列事件。

// just jQuery for mockup - ignore
  $('.relay').on("click", function () {
      $(this).toggleClass("open").toggleClass("closed");
      events.emit("relayChanged", {id:$(this).data("id"), isClosed: $(this).is(".closed")})
  })
  
  
  function RelayMonitor(){
      var relaysClosed = {
         "1": true,
         "2": true
      }
      
      this.init = function(events){
        events.on("relayChanged", (args) => {
            relaysClosed[args.id] = args.isClosed;
            if(Object.values(relaysClosed).every(x => x)) {
                events.emit("allClosed");
            }
        });
      }
  }
  
  //const EventEmitter = require('events'); // included as cdn import here
  var events = new EventEmitter();
  events.on("allClosed", () => console.log("all relays closed"));
var monitor = new RelayMonitor()
monitor.init(events);
.closed {
background-color:green
}

.open {
background-color:red
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/EventEmitter/5.2.5/EventEmitter.js"></script>
<button data-id="1" class="relay closed">Relay1</button>
<button data-id="2" class="relay closed">Relay2</button>

答案 1 :(得分:0)

您应该改用基于事件的结构,例如:

  const EventEmitter = require('events');

  const input = new EventEmitter();

通过这种方式,您可以发出以下事件:

 relay1.watch((err, value) => input.emit("relay1", !!value));

这样,您可以在多个位置将回调附加到中继:

 input.on("relay1", on => console.log(on));

现在,当所有中继都在其上时,就可以轻松获得另一个事件:

 let relaysCount = 0;
 function updateCount(on) {
   if(on) { 
     relaysCount++;
     if(relaysCount === 2)
       input.emit("allOn");
   } else { 
     relaysCount--;
     input.emit("someOff");
  }
 }

 input.on("relay1", updateCount);
 input.on("relay2", updateCount);

现在,像您的示例一样,在开始超时时,如果某些设置为“关闭”,则可以轻松取消该操作:

 input.on("allOn", () => {
    const task = setTimeout(/* sth */, 1000);
    input.on("someOff", () => clearTimeout(task));
 });