32
38

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

JavaScriptで非同期無限ループ

Last updated at Posted at 2015-10-03

非同期無限ループ色々

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(); 
32
38
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
32
38

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?