obniz.repeatが便利なのにあんまり使われていない気がする話


obniz Advent Calendar 2020の16日が開いていたので、
obnizにはobniz.repeatという便利?関数の布教活動してみます。

obniz.repeatはあんまりみんなに使われていない気がするんですよね。

obniz.repeatって何?

obniz.repeatはobnizで繰り返し処理をするときに設定する関数です。
arduinoで言うところのloopですね。

ずっと繰り返してくれる=無限ループだ! ってことで while(true){} と同じだと思われるんですが、
実ははうらで色々やってて、

  • obnizデバイスとの接続が切れたら自動で止まるように
  • 内部でエラーが出ても止まらずに次のループを動かしてくれる

という機能もついています

とりあえずコードで比較

↓動くんだけど、のちにハマりやすい書き方


let obniz = new Obniz("XXXXX");

obniz.onconnct = async ()=>{
   let led = obniz.wired("LED", {xxxx});

   while(true){
      led.on();
      await obniz.wait(1000);
      led.off();
      await obniz.wait(1000);
   }
}

↓おすすめの書き方


let obniz = new Obniz("XXXXX");

obniz.onconnct = async ()=>{
   let led = obniz.wired("LED", {xxxx});

   obniz.repeat(async ()=>{
      led.on();
      await obniz.wait(1000);
      led.off();
      await obniz.wait(1000);
   }, 0); //リピートインターバルが0ms
}

while(true)obniz.repeatの比較です。
書くコード量はどっちもそんなに変わらないし、どちらも同じようにかけます。

ただ、これが途中でデバイスとの接続が切れた!というときに、

while(true)はled.on()がうまく行かなくてthrow
→ try/catchはこのコードで書かれてないので、プログラム全体のエラーとなり、プログラムがクラッシュする

obniz.repeatはthrowをハンドリングして、console.errorに出すだけでクラッシュしなくなる
& 自動で次のループも止めるので正常にプログラムが動き続ける

という違いが生まれます。
とりあえず繰り返し処理したいからwhile(true)だ!というのを、とりあえずobniz.repeatだ!に変えるだけで、ちょっとだけ安全なプログラムになるので、ぜひ使ってください

オプション

obniz.repeatには第2引数があって、インターバル時間を指定できます。
repeatの第1引数で指定した関数を実行するときに、ちょっと待つってことができます。

一番高速で動かしたければゼロを指定すればOKですが、5分に1度だけ動かしたいなと言うときは5分=300,000msなので300000と指定すればOKです

↓5分に1秒だけ光るLED. タイミング見計らうのが難しそう


let obniz = new Obniz("XXXXX");

obniz.onconnct = async ()=>{
   let led = obniz.wired("LED", {xxxx});

   obniz.repeat(async ()=>{
      led.on();
      await obniz.wait(1000);
      led.off();
   }, 300000); //リピートインターバルが300000ms = 5min
}

ライフサイクル

ちなみに、全体的な挙動イメージはこんなライフサイクルになります。

右側に書いてるのはobniz.connectionStateで取れる値です。

obniz.onconnect = async () => {}でプログラムを書いている人が大半だと思いますが、実はobniz.on('connect', async ()=>{})って書き方でもOKだったり・・・!
プログラムの書き方Tipsはそのうちまた記事にしようと思います。