1

dispatchEvent 呼び出しのみを使用して、JavaScript/DOM でイベント ループ メカニズムを作成したいと考えています。

例えば:

document.addEventListener("LoopingEvent", loop, true);
var loop = function() {
    doSomeWork();
    updateUI();
    document.dispatchEvent(loopEvent);
};
var loopEvent = document.createEvent('Events');
loopEvent.initEvent("LoopingEvent", true, true);
document.dispatchEvent(loopEvent);

実行すると、コール スタック OutOfRange エラーがスローされます。ループ ハンドラのディスパッチ呼び出しを window.setTimeout 遅延を使用するように変更すると、エラーなしでループします。

setInterval や setTimeout に頼らずに、dispatchEvent を無限にループさせる方法があるかどうか疑問に思っていますか? dispatchEvent ループ パターンの利点は、設定された時間間隔ではなく、作業が完了したときに呼び出しが発生することです。

洞察を事前にありがとう...

4

3 に答える 3

1

dispatchEventイベントを同期的にターゲットに送信するためdispatchEvent、イベント ハンドラを使用すると、フレームがスタックに蓄積され、最終的にオーバーフローします。

単に「永遠にループ」したい場合は、いくつかの選択肢があります。どちらの選択が正しいかは、コードが他のイベントとどのように相互作用するかによって異なります。あなたのコードは、それがupdateUI(). イベント ハンドラーは、更新された UI を描画できるように、定期的にブラウザーのイベント ループに戻る必要があります。これを達成するには、次を使用setTimeout(loop, 0);するのが良い方法です。

function loop() {
  doSomeWork();
  updateUI();
  setTimeout(loop, 0);
}
loop();  // get things started

will への呼び出しは、再度呼び出されるsetTimeout前に戻ります。loopその後、ブラウザが再び起動loopします。ブラウザーへの呼び出しの合間loopに、UI の変更を描画したり、クリックやその他のイベントに応答して他のイベント ハンドラーを呼び出したりするなど、他のコードが実行される場合があります。

必要に応じて、遅延を 0 ミリ秒からより大きな値に増やすことで、ループの実行をより遅くすることができます。これは、ループがアニメーションを実行している場合に役立ちます。

ループを停止したい場合は、呼び出さsetTimeoutないでください。再度呼び出されることはありません。

ここに別のテクニックがあります:

比較的新しいバージョンの Firefox、Chrome、または Safari を使用している場合は、workers と呼ばれる新しい機能を使用してループを実行できます。ワーカーには独自のイベント ループがあるため、次のようなコードを記述しても問題ありません。

// worker code
while (true) {
  doSomeWork();
  // post messages to update the UI
}

ワーカーは他のスクリプトとは別に実行されます。結果をページ自体にプッシュするには、 という関数を使用する必要がありますpostMessage関連する仕様は次のとおりですが、チュートリアルを検索したり、フォローアップの質問を投稿したりすることもできます。最初は仕様を理解するのが難しい場合があるためです。

于 2010-06-23T13:08:02.227 に答える
0

dispatchEvent()についてコメントすることはできませんが、このパターンの何が問題になっていますか?

function DoSomeWork()
{
   // do work
   if (moreWorkNeedsDoing)
   {
      setTimeout(DoSomeWork, 0);
   }
}

関数は、実行する作業がある限り、「すぐに」反復します。

于 2010-06-23T12:51:52.040 に答える
0

無期限に実行し続ける無限ループを誘発しているようです。他の関数をスレッドでキューに入れるには、実行間のタイマー遅延が必要です。

dispatchEvent ループ パターンの利点は、設定された時間間隔ではなく、作業が完了したときに呼び出しが発生することです。

setTimeout0 ミリ秒の遅延でその効果が得られますが、ループsetTimeoutまたはsetInterval別の無限ループが作成されるため、上記で指摘したように、少なくともある程度の遅延が必要です。

于 2010-06-23T12:46:28.923 に答える