[JavaScript]イベントループ(Event Loop)


[10分TECOTALK]🍗 ピーターのイベントループ(17分)

1朕非同期コード例

console.log('하나'); // 1. 

// 1초 뒤에 첫번째 인자로 들어간 콜백 함수를 실행한다.
setTimeout(function() {
  console.log('셋'); // 3.
}, 1000);
// 첫번째 인자 : 특정 함수의 인자로 들어가는 함수 '콜백 함수'
// 두번째 인자 : 1000ms -> 1초(second)

console.log('둘'); // 2. 

🤔 どうしてそうするの?


  • JavaScriptエンジンがコードの処理中にsettimeoutなどの非同期コードに遭遇した場合、このコードはJavaScriptの後で実行されます.

  • イベントループは、JavaScriptコードを実行するJavaScriptエンジンの後ろにあるコンテキストの一部として実行されるデバイスです.
  • 2朕コールバック関数


  • 別の関数パラメータに渡す関数

  • コールバック受信関数による特定の時点での実行

  • 同期コールバックの場合は、すぐに呼び出します.

  • 非同期コールバックの場合は、後で条件を満たすときに実行します.

  • イベントリスナー、タイマー/XMLHttpRequestリクエスト
  • //  ☑️ 동기 콜백의 예제
    
    function greeting(name) { 
      console.log( '안녕하세요' + name); // 4. 콘솔 로그 출력
    }
    
    function processUserInput(callback) { 
      const name = prompt('이름을 입력해주세요'); // 2. prompt로 이름을 입력받는다.
      callback(name); // 3. 인자로 받은 콜백 함수를 호출한다
    }
    
    processUserInput(greeting); // 1. 함수에 함수를 인자로 넣어준다.
    

    3朕JavaScriptエンジン


    ▼JavaScriptエンジンは、JavaScriptコードを解釈して実行する「interpreter」です。

  • 解釈プログラムとは、プログラミング言語のソースコードを直接実行するコンピュータプログラムまたは環境を指す.
  • 各ブラウザには異なるエンジンタイプがあります。

  • 社のハエはネットポケット、クロムはV 8などです.
  • ▼JavaScriptエンジンは大きく「hip」と「呼び出しスタック」に分けられる。


  • ヒップホップ(Heap)は「メモリ割り当ての一部」(変数やオブジェクトを格納する倉庫)にすぎません.

  • 呼び出しスタック(Call Stack)は「関数が呼び出し順にスタックされたスタック」と考えられる.

  • 関数の実行時に呼び出しスタックに挿入

  • 関数が返されると(関数の実行が完了した)、呼び出しスタックの上部にある対応する関数がポップアップされます.

  • 実際には、関数ではなく、関数実行コンテキスト(Execution Context)です.
  • 「JavaScriptは単一スレッド言語」


    =>1つの呼び出しスタックのみを使用


    =>同時に一つのことしか処理できません。


    🤔 しかし、関数に呼び出しスタックが1つしかない場合、非同期リクエストをどのようにサポートし、同期リクエストを処理しますか?

    4」Webブラウザの構成



    構造の詳細については、[JavaScript]非同期処理とJavaScriptエンジンの動作:)を参照してください.

  • settimeoutを含むDOMメソッドとHTTPリクエストはいずれもJavaScriptエンジン外部のWeb APIが提供するメソッドである.

  • Web APIメソッドは、操作が完了するとすべて非同期メソッドを採用するため、操作が完了するとコールバック関数をコールバックキューに入れる.コールバック関数はそこで実行を待っています.

  • JavaScriptエンジン自体は単一スレッドであるが、Webブラウザは実際には複数のスレッドを使用してJavaScriptを駆動する.より詳細には、Web APIはマルチスレッドである.次に、JavaScriptエンジンに必要なデバイスは、それらと対話するためにコールバックキューとイベントループであると考えられます.
  • プルトニウムイベントループ



    ▼呼び出しスタックと呼び出し行列をじっと見つめていた。


    ▼呼び出しスタックが空の場合は、コールバックキューのコールバック関数を呼び出しスタックに入る順に入れます。



    👀 非同期とtry-catch

    document.querySelector('.btn').click(function() { // (A)
      try {
        $.getJSON('/이런저런 주소', function(res) { // (B)
          // 여기서 에러 🚨
        });
      } catch (e) {
        console.log('속보) 에러 발생: ' + e.message);
      }
    });
    非同期コードを使用すると、try-catchは予想とは異なるエラーをキャプチャできない可能性があります.
    なぜこんなことになったのか調べてみましょう
  • ボタンクリックイベントリスナーがWeb APIに登録されている場合、クリックイベントが発生した場合、イベントリスナーがクリックすると、コールバック関数がコールバックキューに入ります.
  • この場合、Aは、呼び出しスタックが空であるため、イベントループによって呼び出しスタックに移動する.
    (Aダイナミック:Callback Queue->Call Stack)
  • A内部でgetJSONメソッドを実行すると、HTTPリクエストを発行するXMLTTPRequestオブジェクトがコールバック関数とともにWebAPIを生成します.
  • そしてgetJSONメソッドはhttpリクエストを返し、自分のタスクを完了します.また、A関数内部もgetJSONのみなので、自分の操作を実行した後に戻ります.呼び出しスタックが空になります.

  • XMLHTTPRequestもHTTPリクエストの送信に伴って消失し、コールバック関数Bはコールバックキューに入る.呼び出しスタックが空の場合、Bはイベントループによって呼び出しスタックに移動する.(Bアクティビティ:Web API->Callback Queue->Call Stack)
    ⑪」Bが呼び出しスタックに移動した時点で、Aは実行を完了して戻ってきた.すなわち,AとBは全く異なる文脈でそれぞれ動作する.
    したがって、A内部のtry-catch文では、Bで発生したエラーをキャプチャできません.
  • try-catchでBで発生したエラーをキャプチャしたい場合は、答えは簡単です。


    =>Bのtry-catchドアはB内部に置けばいいです🤭
    document.querySelector('.btn').click(function() { // (A)
      $.getJSON('/이런저런 주소', function(res) { // (B)
        try {
          // 여기서 에러 🚨
        } catch (e) {
          console.log('속보) 에러 발생: ' + e.message);
        }
      });
    });

    🌐 リファレンスリンク

  • [10分TECOTALK]🍗 ピーターのアクティブループ-https://youtu.be/wcxWlyps4Vg