JavaScript Event Loopの概要

3394 ワード

最近、Nodejsを学ぶ過程で という概念を深く理解し、Nodejsをよりよく使用するために、これらの概念は知られていない.以前はJavaScriptのユーザーとして機能していたが、どのように動作しているのかは全く分からず、多くの概念に対しても「その理由を知っている」.
クライアントのJavaScriptNodejsにとってはそれほど差はありませんが、今回はクライアント側からEvent Loopという概念についてお話ししましょう. の切り込み点の一つでしょう.実はjQueryの作者John Resigは数年前に良い文章How JavaScript Timers Workを書いて、timer がブラウザの中でどのように働いているのかを述べて、私もこの文章を通じてやっと“その理由を知っています”.
質問シーン
まずコードを見てみましょう.
1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

  <a href="#" id="doBtn">do something</a>

  <div id="status"></div>

  <script type="text/javascript">

    void function() {

      var doBtn = document.getElementById('doBtn')

        , status = document.getElementById('status');



      doBtn.onclick = function(e) {

        e.preventDefault();



        status.innerText = 'doing...please wait...';  //   

        sleep(10000);  //             ,10s

        status.innerText = 'done';  //   

      };

    }();



    function sleep(ms) {

      var start = new Date();

      while (new Date() - start <= ms) {}

    }

  </script>


上のコードは主に1つの机能を完成したいです:ボタンがクリックされた时------>1つの状态を表示してユーザーにいくつかの事をしていることを知らせます------>仕事を始めます------>仕事が终わった后に状态はすでに完成しましたに変更します.
問題ないように見えますが、仕事ができるはずなので、ブラウザでこのページを実行します.しかし、現実はいつも残忍で、予想された効果に合っていない.ボタンをクリックするとブラウザがフリーズし、表示状態のdivは表示されず、インタフェースにも「doing...」は表示されません.このヒント;10sを経過した後、ブラウザは気を取り戻し、時間のかかる計算が終了したことを表し、このとき表示状態に使用されるdivは「done」を表示する.
その原因を究明します:JavaScriptエンジンは単一のスレッドのです.この場合、ブラウザカーネルにどのような主要な常駐スレッドがあるのかを理解してこそ、上記の疑問を解くことができる.ブラウザカーネル常駐スレッドには、次のようなものがあります.
  • ブラウザGUIレンダリングスレッド
  • JavaScriptエンジンスレッド
  • ブラウザタイミングトリガスレッド
  • ブラウザイベントトリガスレッド
  • ブラウザhttp非同期要求スレッド
  • 一方、GUIレンダリングスレッドとJavaScriptエンジンスレッドは反発し、JavaScript実行時にGUIレンダリングスレッドは保留され、ページはすべての解析とレンダリング動作を停止します.上記の3、4、5クラスのスレッドでも異なる非同期イベントが発生します.次の図を見ると直感的に見えるはずです.
    JavaScript-Event-Loop
    JavaScriptエンジンは単一スレッドなので、コードはキューに押され、エンジンが先進的な先発方式で実行されます.イベント処理関数、timer実行関数もこのキューに並べられ、無限ループを利用してキューヘッダから関数を取り出して実行されます.これがEvent Loopです.
    次に、上記のコードがなぜ予想された効果に達しなかったのかを図で説明し続けます.
    すると結局「done」しか見えませんでした.
    どうやって解決しますか?setTimeout()を使用します.次に、変更されたonclickイベント処理関数を示します.
    1
    
    2
    
    3
    
    4
    
    5
    
    6
    
    7
    
    8
    
    9
    
    10
    
    
    doBtn.onclick = function(e) {
    
      e.preventDefault();
    
    
    
      status.innerText = 'doing...please wait...';  //   
    
      
    
      setTimeout(function() {
    
        sleep(10000);  //             ,10s
    
        status.innerText = 'done';  //   
    
      }, 0);  // 0ms delay
    
    };
    
    

    どうしてこれで解決したのですか.やはり上のキューの図で説明します.
    JavaScript