web-dev-qa-db-ja.com

ブラウザーがタイムアウトと間隔をクランプするのはなぜですか?

ブラウザーでイベントループをブロックせずに大量のデータセットを処理するために、setTimeoutおよびsetIntervalのいくつかの抽象化に取り組んできました。

このとき、タイムアウトまたは間隔に指定したミリ秒数をブラウザが「クランプ」することを発見しました。

たとえば、setTimeout('do something', 0)と記述すると、ブラウザは実際にsetTimeout('do something', 4)を実行します。つまり、コードが実行されているブラウザとバージョンに応じて、ブラウザは最低2〜10ミリ秒を強制します。

これは、コールバック/約束が待機する時間に大きな影響を与える可能性があります。とにかく(タイムアウトの場合)postMessageまたはMessageChannel(私の考えでは貧弱なソリューション)を使用するなど、これを回避する方法があります。実質的に待機時間がゼロである場合、タイムアウトと同じ効果を提供できます。

なぜブラウザはこのようにタイムアウトと間隔をクランプするのですか?私はこれについて、公式であろうとなかろうと、理由を見つけることができません。私の唯一の仮説は、どういうわけか、他のタスクをコールスタックに追加できるようにすることですが、これはpostMessageで問題ないと思われるため、それ以上はできません。これが誰にも役立つ理由を考えてください。

4
Ravenstine

その理由についてはあまりお伝えできませんが、この件についての調査に役立つ「公式」のドキュメントに従ってください。

上記のすべてのHTML 5仕様には、調査を続行するための興味深いヒントが含まれている可能性があります。

MDNドキュメンテーション setTimeoutについて:

最小/最大の遅延とタイムアウトのネスト

歴史的にブラウザはsetTimeout()の「クランプ」を実装しています。遅延が「最小遅延」の制限よりも小さい連続したsetTimeout()呼び出しは、少なくとも最小遅延を使用するように強制されます。最小遅延DOM_MIN_TIMEOUT_VALUEは4ミリ秒(Firefoxの設定に保存されています:dom.min_timeout_value)、DOM_CLAMP_TIMEOUT_NESTING_LEVELは5ミリ秒です。

実際、4msは HTML5仕様 で指定されており、2010年以降にリリースされたブラウザー全体で一貫しています。 (Firefox 5.0/Thunderbird 5.0/SeaMonkey 2.2)以前は、ネストされたタイムアウトの最小タイムアウト値は10ミリ秒でした。

「クランプ」に加えて、後でページ(またはOS /ブラウザ自体)が他のタスクでビジー状態になったときにタイムアウトが発生する可能性もあります。

最新のブラウザーで0ミリ秒のタイムアウトを実装するには、 window.postMessage()ここで説明 として使用できます。

Internet Explorer、Chrome、Safari、Firefoxなどのブラウザーは、遅延を32ビットの符号付き整数として内部的に保存します。これにより、2147483647より大きい遅延を使用すると整数オーバーフローが発生し、タイムアウトがすぐに実行されます。

3
edalorzo