QA@IT

setTimeoutで0msを指定するイディオムの意味は?

4828 PV

あるJavaScriptのコード ( realtime-cube ) を眺めていたら、以下のような箇所がありました。

  setTimeout(function() {
    updateForRealTimeDoneInitializing();
    setTimeout(function() {
      updateCollaborators();
      setTimeout(function() {
        initCube();
      }.bind(this), 0)
    }.bind(this), 0);
  }.bind(this), 0);
}

分からないところがあるので、どなたか教えていただけませんでしょうか。

  1. setTimeout(someFunction, 0) というイディオムの意味は?
  2. なぜsetTimeoutはネストしているのか?

いまの私の理解では、ここで呼び出している初期化ぽいの3つの関数は、それなりに(通信系の待ちなどがあって?)時間がかかることもあるので、その処理が終わるのを待たずに処理を進めるためのイディオムなのかなというところです。

非同期で処理を進めるにしても、ネストしておくことで、

    updateForRealTimeDoneInitializing();
         
      updateCollaborators();
         
        initCube();

と確実に上の関数から戻ってきたことを保証できる、ということかなと想像していますが、それで合ってますでしょうか?

良く分かってないのですが、もしかしてこの辺は promise とか deferred といったパターンが使えるライブラリなら、スッキリ書けるものでしょうか?

回答

setTimeout(someFunction, 0)の意図は、イベントループの次回で即時実行するという意味で、nodeのprocess.nextTick()みたいなものです。(微妙に実装依存で違いがあるようですが)

UIとかリアルタイム系の処理をするときには、まとまった計算コストのかかるシリアルな処理を分割して、なるべく1ループあたりのブロック時間(といっても、この場合はI/OではなくCPU)を短くして、負荷を時間軸で分散することがあります。そうしないと、1回のループで16ms以上かかったら60fpsを達成できずカクカクしてしまうからです。

この例については推測ですが、updateForRealTimeDoneInitializingupdateCollaboratorsinitCubeがそれぞれ結構CPU的に重い処理で、3ループに分割することで、3つ全部終えるには48ms近くかかる遅いCPUでも60fpsを達成しようとしている、みたいな感じではないでしょうか。

編集 履歴 (1)
  • なるほど、イベントループの次回なんですね。イベントループが処理モデルの根本にあるという理解が抜けていたのがスッキリしなかった理由という気がします。ありがとうございます。 -
  • イベントループの次回になる実装は皆無だと思います
    あくまでなるべく早くお願いねということでしかありません

    process.nextTickに近いのはsetImmediateです
    こちらはそれなりに信頼できます
    -
ウォッチ

この質問への回答やコメントをメールでお知らせします。