2025/09/01 19:20 Why do browsers throttle JavaScript timers?

ロボ子、今日のITニュースは`setTimeout(0)`の意外な挙動についてじゃ。

`setTimeout(0)`、ですか?すぐに実行されると思っていましたが…。

そう思うじゃろ?でも実際には、ブラウザによっては4ms後に実行されることがあるんじゃと!

4msも遅延するんですか?それはなぜでしょう?

ブラウザがバッテリー消費を抑えたり、インタラクティブ性を保つために、`setTimeout`の最小時間を4msに設定しているからじゃ。レガシーEdgeやChromeのバックグラウンドタブでは、もっと厳しくスロットリングされることもあるらしいぞ。

なるほど。`fake-indexeddb`でIndexedDBトランザクションの自動コミットに`setTimeout`を使った際に、Chromeで遅延が発生したのは、この影響だったんですね。

`fake-indexeddb`だと、Node.jsに比べてChromeで16倍も遅延したらしいのじゃ。これは深刻じゃな。

代替手段はあるのでしょうか?

`setImmediate`、`MessageChannel.postMessage`、`window.postMessage`、`scheduler.postTask`といった選択肢があるぞ。

それぞれの性能はどうなんでしょう?

ベンチマークによると、ChromeとFirefoxでは`setTimeout`が4msに制限されるけど、他の選択肢はほぼ同等みたいじゃ。Safariでは`setTimeout`がさらに制限されるらしい。

`fake-indexeddb`では、最終的に`scheduler.postTask`を採用したんですね。

そうじゃ。フォールバックとして`MessageChannel.postMessage`か`window.postMessage`を使うみたいじゃな。

なぜブラウザは`setTimeout`を制限するんでしょう?

Web開発者がAPIを過度に使ったり、より良い選択肢を知らないからじゃ、とのことじゃ。

`scheduler.postTask`と`postMessage`は、今のところスロットリングされないと予測されているんですね。

当面は大丈夫そうじゃな。`setInterval`についても、`setTimeout`と同様のことが言えるらしいぞ。

`fake-indexeddb`では、Safariで`setTimeout`が`MessageChannel`や`window.postMessage`よりも優先されるという興味深い現象も確認されたんですね。

ブラウザごとの挙動の違い、奥が深いのじゃ。しかし、setTimeoutがsetTimeoutしないとは、これいかに?

まるで、待ち合わせに遅刻してくる人のようですね。

うむ。setTimeoutだけに、時間通りにセットしてくれ!…って、ダジャレじゃ!
⚠️この記事は生成AIによるコンテンツを含み、ハルシネーションの可能性があります。