【MESH カスタムタグ】ミリ秒単位で処理をsleepさせる方法

#できること
MESH*アプリ上で、処理を**ミリ秒単位で指定してsleep**させることが出来ます。
これを利用する事でミリ秒単位でずらしたアクションを実行するというニッチなニーズに答えることができます。

*MESHとは、小さな便利を形にできる、ブロック形状の電子タグです。
- [MESH：小さな便利を形にできる、ブロック形状の電子タグ](http://meshprj.com/jp/)
<br>

![sleepタグ.gif](https://qiita-image-store.s3.amazonaws.com/0/159447/a5334384-ed28-bc3a-65d4-2e40beac9759.gif)
真中の砂時計アイコンが今回作ったカスタムタグです。青い枠が現在処理されているタグなのですが、作成したタグが意図通りLEDで設定している1.5秒と同じ時間だけ処理をsleepさせて、その次のアクションを実行しています。

#新たに作った理由

①ロジックのタイマータグで待つ(sleep)では、秒単位の指定しかできない
![IMG_0135.jpg](https://qiita-image-store.s3.amazonaws.com/0/159447/38fe8149-a904-60ec-b9d1-c44ff921eca7.jpeg)


②LEDタグの点灯する時間を利用すれば、0.1秒単位で指定できるがそのためだけにLEDタグを使うのも微妙
![IMG_0136.jpg](https://qiita-image-store.s3.amazonaws.com/0/159447/d9f68da9-ec97-1097-6595-022dea471130.jpeg)

#実装
色々と試した結果、Promiseを使って期待したsleepの動作が実現しました。
これによって、メイン処理を止めずに必要な所だけ待機指定ができます。

###importファイル
```millisecond_sleep.json
{"formatVersion":"1.0","tagData":{"name":"wait","icon":"data:image/png;base64,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","description":"","functions":[{"id":"function_0","name":"ミリ秒単位で待つ時間を指定","connector":{"inputs":[{"label":""}],"outputs":[{"label":""}]},"properties":[{"name":"時間(ミリ秒)","referenceName":"millisecond","type":"number","defaultValue":"1000"}],"extension":{"initialize":"","receive":"","execute":"wait().then((v) => {\n    log(\"wait \" + v + \" millisecond\");\t\n\t\n\tcallbackSuccess( {\n\t\tresultType : \"continue\"\n\t} );\n});\n\nfunction sleep() {\n\treturn new Promise(resolve => setTimeout(resolve,properties.millisecond));\n}\n\nasync function wait() {\n\t//非同期処理が完了するまで待機\n\tawait sleep();\n\t\n\treturn properties.millisecond.toString();\n}\n\nreturn {\n\tresultType : \"pause\"\n};\n","result":""}}]}}
```

###Initialize, Receive, Result
特に書くことはありません。

###Execute


```Execute_success.js
wait().then((v) => {
    log("wait " + v + " millisecond");	
	
	callbackSuccess( {
		resultType : "continue"
	} );
});

function sleep() {
	return new Promise(resolve => setTimeout(resolve,properties.millisecond));
}

async function wait() {
	//非同期処理が完了するまで待機
	await sleep();
	
	return properties.millisecond.toString();
}

return {
	resultType : "pause"
};
```

#失敗した実装
単純に開始時間を保存しておいて、開始時刻から指定秒数経ってwhile文を抜けるsleepの方法です。
ビジーウェイト(Busy Waiting)させるため、並列で動いている他のタグの処理にも影響してsleepさせてしまった失敗した実装方法です。備忘録のために書き残しています。

###Initialize, Receive, Result
特に書くことはありません。

###Execute

```Execute_failure.js
wait();

function wait(){
	var time1 = new Date().getTime();
	var time2 = new Date().getTime();

	while ((time2 -  time1)<properties.millisecond){
			time2 = new Date().getTime();
	}
}
```

#感想
細かくタイミングをずらしたい事が多々あったので、地味でニッチなカスタムタグだけど個人的には凄い便利でした！

#参考
[要注意？！JavaScriptでsleepする5つのTips](https://www.sejuku.net/blog/24629)