ブラウザとノード.jsのイベントループ(Even Loop)


事件の輪の紹介
イベントループとは、イベント、ユーザインタラクション、スクリプト、レンダリング、ネットワーク、ユーザーエージェントの動作を調整するために発生する仕組みである.
一.ブラウザ内のイベントループ
私達はすべてjavascriptが単一スレッドであることを知っています.タスクは一つずつ順番に実行する必要があります.もしjavascriptに二つのスレッドがあり、一つはDOMのために様式を追加し、一つはDOMを削除すると混乱します.シングルスレッドはメモリを節約することができますが、前のタスクが完了するまで次のタスクを実行することができます.上記の図のように、ブラウザ内のイベントのループ図には、次のようなものが含まれています.
  • heap(ヒープ):ユーザーが自発的に要求して分割したメモリ領域、例えばnewのオブジェクトは、一つのオブジェクトをヒープの中に入れて、heapのオブジェクトとして理解することができます.
  • スタック:関数動作により一時的に占有されたメモリ領域は、関数がスタックに保存されます.
  • Event Loop:
  • すべての同期タスクがメインスレッド上で実行され、実行スタックが形成される.
  • 非同期タスクが実行結果を得ると、タスクキュー(キューは先進的なデータ構造であり、スタックは先進的なデータ構造である)にイベント
  • を配置する.
  • スタック内の全同期タスクの実行が完了すると、システムはタスクキューを読み込み、キュー内のイベントをStckに入れて順次実行する.すなわち、非同期タスクのコールバック関数を実行する.この過程は循環が絶えないので、これはEvent Loopです.
  • マクロタスク(MacroTask)とマイクロタスク(MicroTask)
  • ブラウザにおけるマクロタスク(MacroTask)の方法は、setTimeout setInterval
  • である.
  • ブラウザにおけるマイクロタスクの方法は、Promise.then Message Channel Promise.then Message Chanel
  • である.
    実行プロセス
    *             。
    *   Microtask Queue         。
    *   Macrotask Queue       。
    *   Microtask Queue         。
    *         。
    
    例を挙げて説明します
    console.log(1);
    setTimeout(function(){
        console.log('settimeout1');
        new Promise(function(resolve,reject){
        console.log('promise');
       	resolve();
        }).then(res=>{
       console.log('promise.then');
        })
    });
    setTimeout(function(){
       console.log('settimeout2');
        })
    console.log(2);
    
    ブラウザで出力する結果の順序は以下の通りです.
    1
    2
    settimeout1
    promise
    promise.then
    settimeout2 
    
    分析:
    まず、スタックにおける同期タスクを実行し、先にconsolone.log(1)とconsolone.log(2)を実行する.
    次にsetTimeoutに会ったら、それらのコールバック関数をMacroTaskに入れます.
    その後、タスクキューのコールバック関数をメイン実行スタックに順次入れて実行し、consolone.log('settimeout 1')に続き、promiseは直ちに実行され、promise.thenはマイクロタスクをMicroTaskに入れて先に実行される.
    最後に2番目のset Timeoutのコールバック関数consolone.log('settimeout 2')を実行します.
    二.node.jsの中の事件の輪
    even loopはNode.jsが起動すると、Eventloopを初期化し、提供された入力スクリプトを処理し(非同期API呼び出しが発生する可能性がある)、Event loopを処理します.スレッドが一つしかありません.それはEvent循環運行のスレッドです.イベントサイクルは循環順序で動作し、異なる段階を持つ.NodeでのEvent loopの動作手順は上の通りです.
  • タイマーは、この段階でsetTimeout()とset Interval()のようなタイマキューの中のコールバックを実行する.
  • I/Oコールバック(I/O calbacks)はこの段階でほぼすべてのコールバックを実行します.ただし、closeイベント、タイマー、setImmedite()のコールバックは含まれません.
  • アイドル状態で、準備段階は内部でのみ使用され、無視できます.
  • ポーリング(poll)は新しいI/Oイベントを待っています.nodeはいくつかの特殊な状況でここにブロックされます.
  • チェック(check)setImmedite()のフィードバックはこの段階で
  • を実行します.
  • マクロタスク(MacroTask)とマイクロタスク(MicroTask)
  • コールバックをオフにします.
  • 実行プロセス
  • は、第1のサイクルに入る前に、まず次のような動作を行います.1.同期タスク2.非同期要求3.計画タイマの発効時間4.process.nextTick()
  • を実行します.
  • は、現在のサイクル内のTimers Que(条件を満たすsetTimeout、set Intervalコールバックを実行する)をクリアし、NextTick Queをクリアし、Microtask Queをクリアします.
  • は、現在のサイクル内のI/O Que(I/O操作を実行するコールバック関数)をクリアし、NextTick Queをクリアし、Microtask Queをクリアします.
  • は、現在のサイクル内のCheck Queをクリアし、NextTick Queをクリアし、Microtask Queをクリアします.
  • は現在のサイクル内のClose Queをクリアし、Next Tick Queをクリアし、Microtask Queをクリアします.
  • は次のサイクル
  • に入ります.
        :nextTick    promise microtask 。setTimeout setInterval    setImmediate 。
    
    例えば、ブラウザのEvent LoopとnodeのEvent Loopは違っています.上記の同じ例示的なコードをnode環境で実行します.
    console.log(1);
    setTimeout(function(){
        console.log('settimeout1');
        new Promise(function(resolve,reject){
        console.log('promise');
       	resolve();
        }).then(res=>{
       console.log('promise.then');
        })
    });
    setTimeout(function(){
       console.log('settimeout2');
        })
    console.log(2);
    
    node環境での出力結果の順序は以下の通りです.
    1
    2
    settimeout1
    promise
    settimeout2
    promise.then
    
    nodeの環境では、まず実行スタックは現在のタスクキュー、つまり2つのsetTimeoutの中のコールバック関数を実行してから、マイクロタスクキューを実行します.promise.thenは最後に実行します.
    転載先:https://juejin.im/post/5b38d5a5e51d4558a3055094