非同期無限ループ色々
FRAME_PER_SEC = 60; // [frames/s]
FRAME_TIME = 16; // [ms/frame]
setInterval
(Browser, Node)
setInterval(function() {
console.log(Date.now());
}, FRAME_TIME);
0の指定は可能ですが、少なくとも4msは間隔が空くようです。また、この最小間隔はランタイム依存なので、0にはしないほうが良いでしょう。
setTimeout
(Browser, Node)
(function loop() {
setTimeout(loop, FRAME_TIME);
console.log(Date.now());
})();
setInterval
と所感は同じ。
requestAnimationFrame
(Browser)
var timer = Date.now();
(function loop() {
var now = Date.now();
if (now - timer > FRAME_TIME) {
console.log(now);
timer = now;
}
requestAnimationFrame(loop);
})();
フォアグラウンドのタブで60FPSで実行されるということになっています。
process.nextTick
(Node)
var timer = Date.now();
(function loop() {
var now = Date.now();
if (now - timer > FRAME_TIME) {
console.log(now);
timer = now;
}
process.nextTick(loop);
})();
setImmediate
(Browser, Node)
var timer = Date.now();
(function loop() {
var now = Date.now();
if (now - timer > FRAME_TIME) {
console.log(now);
timer = now;
}
setImmediate(loop);
})();
Promise
(Browser, Node)
Promise.resolve(0).then(function loop() {
var now = Date.now();
return new Promise(function(resolve) {
if (now - timer > FRAME_TIME) {
console.log(now);
timer = now;
}
resolve();
}).then(loop);
});
へ~という感じですが、ぱっと見普通じゃないですし、メモリも食い潰します。
どれを使うべきなのか
Browser
- 使えるなら
requestAnimationFrame
- タブがbackgroundの時にCPUを食い潰さない。
- と見せかけて、もはや
setTimeout
でもいいんじゃねという話もある様子 -
setInterval
は良く分からない。- ループ止めるのに戻り値の管理が必要なのがAPIとして使いづらいと感じているので、個人的にはほぼ使わない
-
setImmediate
は今のところIEでしかサポートされていないようなのでスルー。
Node
まずは以下を読むべし。
http://jxck.hatenablog.com/entry/for-with-eventloop
- I/Oイベントの前が良いなら
process.nextTick
- I/Oイベントの後が良いなら
setImmediate
- delayを指定したいなら
setTimeout
でも良いと思う。-
setTimeout(, 0)
な用途ならsetImmediate
のほうが適切(体感はほぼ変わらないとは思いますが...)
-
ちなみにプログラムはイベントが無くなった時点で終了します。
var prime = 997;
(function loop() {
var now = Date.now();
if (now % prime) {
process.nextTick(loop);
} else {
console.log(now + " = " + prime + " * " + (now / prime));
}
})();
// 以下を入れれば当然即終了
//process.exit();