JavaScriptタイマーの仕組みについて

4198 ワード

原文:John Resig http://ejohn.org/blog/how-javascript-timers-work/
How JavaScript Timers Work
 
基本的な面では、JavaScriptのタイマーがどのように機能しているかを理解することが重要です.タイマーの実行は、JavaScriptエンジンが単一スレッドであるため、私たちの直感的な想像とはよく違います.まず、次の3つの関数がタイマをどのように制御するかを認識します.
  • var id = setTimeout(fn, delay);-タイマーを初期化し、指定した時間間隔後に実行します.この関数は、タイマをキャンセルするために使用できる一意のフラグID(Numberタイプ)を返します.
  • var id = setInterval(fn, delay);-settimeoutと似ていますが、キャンセルされるまで関数(時間間隔はdelayパラメータ)を連続的に呼び出します.
  • clearInterval(id);,clearTimeout(id);-タイマーID(settimeoutとsetIntervalの戻り値)を使用してタイマーコールバックの発生をキャンセルする
  • .
    タイマの内在的な実行原理を理解するために,タイマの遅延(delay)は保障されないという重要な概念を検討する必要がある.すべてのJavaScriptコードは1つのスレッドで実行されるため、すべての非同期イベント(マウスクリックやタイマーなど)は実行機会がある場合にのみ実行されます.良いグラフで説明します.
     
    (大図をクリック)
     
    このグラフには多くの情報を理解する必要があります.完全に理解すれば、JavaScriptエンジンが非同期イベントをどのように実現するかをよく認識することができます.これは1次元のアイコンです:垂直方向は時間を表し、青いブロックはJavaScriptコード実行ブロックを表します.例えば、最初のJavaScriptコード実行ブロックは約18 ms、マウスクリックでトリガーされたコード実行ブロックは11 msなどである.
    JavaScriptエンジンでは、同じ時間に1つのコードしか実行されないため(JavaScript単一スレッドの性質のため)、JavaScriptコード実行ブロックごとに他の非同期イベントの実行が「ブロック」されます.これは、非同期イベント(例えば、マウスクリック、タイマトリガ、またはAjax非同期要求)が発生すると、これらのイベントのコールバック関数が実行キューの最後に実行を待つことを意味する(実際には、ブラウザによってキューの仕方が異なるため、ここでは簡略化されている).
    最初のJavaScript実行ブロックから検討を開始し、最初の実行ブロックでは2つのタイマが初期化される:1つの10 msのsetTimeout()と1つの10 msのsetInterval().タイマが初期化されるタイミング(タイマの初期化が完了するとタイマが開始される)に応じて、タイマは実際に最初のコードブロックが実行される前にトリガーされます.ただし、タイマーにバインドされている関数はすぐには実行されません(JavaScriptが単一スレッドであるため、すぐに実行されません).実際には,遅延された関数は実行キューの最後に順次並べられ,次の適切な時間の再実行を待つ.
    また、最初のJavaScript実行ブロックでは、「マウスクリック」イベントが発生しました.JavaScriptコールバック関数はこの非同期イベントにバインドされています(ユーザーがいつこの(クリック)イベントを実行するかは知られていませんので、非同期と考えられています).この関数はすぐに実行されず、上のタイマと同様に実行キューの最後に並べられ、次の適切な時に実行されるのを待っています.
    最初のJavaScript実行ブロックの実行が完了すると、ブラウザはすぐにどの関数(文)が実行を待っているのかと質問します.このとき、「マウスクリックイベント処理関数」と「タイマコールバック関数」が実行を待っています.ブラウザは(実際には「マウスクリックイベントの処理関数」を選択します.図から先進的なキューであることがわかります)すぐに実行されます.タイマコールバック関数は、次の適切な時間に実行されるのを待っています.
    なお、「マウスクリックイベント処理関数」が実行されると、setIntervalのコールバック関数が初めてトリガーされる.setTimeoutのコールバック関数と同様に、実行キューの最後の実行待ちに並べ替えられます.ただし、setInterva lコールバック関数が2回目にトリガーされた場合(setTimeout関数がまだ実行されている場合)setTimeoutの1回目のトリガーは破棄されることに注意してください.長いコードブロックが実行されている場合、すべてのsetIntervalコールバック関数を実行キューの後ろに配置することができ、コードブロックが実行された後、結果としてsetIntervalコールバック関数の列が実行を待つことになり、これらの関数の間には全部分が完了するまで間隔がありません.したがって、ブラウザは、より多くのintervalの処理関数がキューに並んでいない場合に、次の処理関数をキューの最後に並べ替える傾向がある(これは、間隔の問題のためである).
    3番目のsetIntervalコールバック関数がトリガーされると、前のsetIntervalコールバック関数が実行されることが分かった.これは、setIntervalが現在何を実行しているのかを考慮せず、すべての詰まった関数をキューの末尾に並べているという重要な事実を示しています.これは,2回のsetIntervalコールバック関数間の時間間隔が犠牲になる(縮小する)ことを意味する.
    最後に、2番目のsetIntervalコールバック関数が実行されると、JavaScriptエンジンの実行を待つプログラムはありません.これは、ブラウザが新しい非同期イベントの発生を待っていることを意味します.50 msで新しいsetIntervalコールバック関数が再びトリガーされ、このとき、実行ブロックがその実行をブロックすることはありません.すぐに実行されますsetTimeoutsetIntervalの違いを一例で説明しましょう.
      setTimeout
    (
    function
    (
    )
    {
        
    /* Some long block of code... */
        setTimeout
    (arguments.
    callee, 
    10
    );
      
    }, 
    10
    );
      
      setInterval
    (
    function
    (
    )
    {
        
    /* Some long block of code... */
      
    }, 
    10
    );
     
    この2つのコードは一見違いはありませんが、違います.settimeoutコールバック関数の実行と前回の実行との間隔は少なくとも10 ms(より多くなるかもしれませんが、10 ms未満ではありません)あり、settIntervalのコールバック関数は、前回実行が完了したかどうかにかかわらず、10 msおきに実行しようとします.
    ここで私たちは多くの知識を学び、まとめました.
  • JavaScriptエンジンは単一スレッドであり、すべての非同期イベントキューを強制して
  • の実行を待つ
  • setTimeoutsetIntervalは、非同期コードを実行する際に根本的に異なる
  • を有する.
  • タイマがブロックする直ちに実行できない場合、それは次の実行可能な時点まで実行を遅らせる(所望の時間間隔よりも長い)
  • .
  • setIntervalコールバック関数の実行時間が十分に長い場合(指定された時間間隔よりも長い場合)、それらは連続的に実行され、互いに時間間隔がない.

  • これらの知識点は非常に重要です.JavaScriptエンジンがどのように動作するか、特に大量の非同期イベント(連続)が発生した場合、高度なアプリケーションの構築に基礎を築くことができます.