webウォーカー

9074 ワード

  • は、ウェブワーカーHTML 5を紹介し、バックグラウンドで動作するJavaScriptは、他のスクリプトと独立して、ページの性能に影響を与えません.何でもやりたいことを続けることができます.クリックしたり、内容を選択したりして、web workerはバックグラウンドで実行します.
  • は、JSにマルチスレッドの動作環境を作成し、メインスレッドがウォーカースレッドを作成し、タスクを後者に割り当て、メインスレッドが実行されている間にウォーカースレッドが動作し、互いに干渉せずに、ウォーカースレッドが実行された後に結果をメインスレッドに戻すことができます.このようにする利点は、メインスレッドは、計算集約型または高遅延タスクをワーカースレッドに実行させることができ、これにより、メインスレッドが容易になり、ブロックされたり遅くなったりしないことである.これはJS言語自体がマルチスレッド能力をサポートしているという意味ではなく、ブラウザがホスト環境としてJSのマルチスレッド実行環境を提供している.しかし、ワーカーは新しいものを作ると、いつもメインスレッドの活動に中断されないので、いつでもメインスレッドの通性に応えます.しかし、資源の浪費を招くので、使いすぎないように注意してください.
  • 互換性
    Browser
    IE
    Edge
    FireFox
    Chrome
    Safari
    version
    10+
    12+
    3.5+
    4+
    4+
  • 使用
  • 注意事項:
  • ソース制限:Workカースレッドに割り当てられたスクリプトファイルは、メインスレッドのスクリプトファイルと同じソースでなければなりません.
  • DOM操作制限:Workカースレッドが存在するグローバルオブジェクトは、メインスレッドとは異なり、ホームスレッドが存在するウェブページのDOMオブジェクトを読み取ることができません.documentwindowなどのオブジェクトを取得することもできないが、navigatorlocation( )XMLHttpRequestsetTimeout などのブラウザAPIを取得することができる.
  • 通信制限:Workerスレッドとメインスレッドは同じコンテキストではなく、直接通信できないので、メッセージを通じて完了しなければなりません.
  • スクリプト制限:Workerスレッドはalert()方法とconfirm()方法を実行できませんが、XMLtHttpRequestオブジェクトを使用してAJAX要求を発行することができます.
  • ファイル制限:Workカースレッドはローカルファイルを読めません.すなわち、マシンのファイルシステムを開けません.ロードされたスクリプトは、ネットワークから必要です.
  • 例:
  • メインスレッド
  • Workカースレッドを作成する:
  • //      
    var myWorker = new Worker(jsUrl, options);
    
    Workカー()構造関数は、最初のパラメータはシナリオのURLです.このパラメータは必要であり、JSスクリプトをロードするしかないです.そうでなければエラーが発生します.第二のパラメータは、設定オブジェクトであり、オブジェクトは選択可能である.一つの役割は、Workカーの名前を指定して、複数のWorkerスレッドを区別することです.
  • マスタスレッドコード例:
  • 
    
    myworker :
    // Worker if ( typeof ( Worker ) === 'undefined') document.writeln(' Sorry! No Web Worker support.. ') else { // worker let worker = new Worker('webWork.js', { name : 'worker' }); // worker.postMessage('Hello World'); // worker.postMessage({method: 'echo', args: ['Work']}); // worker.onmessage = function (event) { console.log('Received message ' + event.data); doSomething(); } function doSomething() { // worker.postMessage('Work done!'); // worker.terminate(); } // myworker let myworker = new Worker('webWork2.js', { name : 'myworker' }); // myworker myworker.onmessage = (e) => { document.getElementById("app").innerHTML = e.data } // mywork function stopWorker () { myworker.postMessage('stop'); // myworker , 。 myworker.terminate(); } }
  • Workカースレッド
  • Workカースレッドコード例:
  •   // webWork.js
    
      console.log(self.name,'webWork.js');
    
    // self       ,         。
    
    // //        
    // self.addEventListener('message', function (e) {
    //   console.log(e.data,'data')
    //   self.postMessage('You said: ' + e.data);
    // }, false);
    
    //       onmessage      
    self.onmessage = (e) => {
        console.log(e.data,'e')
    self.postMessage('You said: ' + e.data);
    if (e.data == 'Work done!') {
      self.close();
      }
    }
    
     // webWork2.js
    
     console.log(self.name,'webWork2.js');
    
    //                
    let i = 1;
    function add () {
     i ++;
     self.postMessage(i);
     setTimeout(add, 1000);
    }
    
    add();
    
    //        
    self.onmessage = (e) => {
       if (e.data == 'stop') {
           self.close();
       }
    }
    
    
  • Workカーがスクリプトを読み込みます.
  • Workカーの内部に他のスクリプトをロードする場合、専用のfile://があります.
  • //       
    importScripts('script1.js');
      
    //       
    importScripts('script1.js', 'script2.js');
    
  • エラー処理
  • メインスレッドは、Workカーにエラーが発生したかどうかを傍受することができる.エラーが発生すると、WorkカーはメインスレッドのimportScripts()イベントをトリガする.
      worker.onerror(function (event) {
      console.log([
      'ERROR: Line ', e.lineno, ' in ', e.filename, ': ', e.message
      ].join(''));
    });
    
    //   
    worker.addEventListener('error', function (event) {
        // ...
      });
    
  • Workカー内部でもerror事件を傍受することができる.
  • Workカーを閉じます.
  • 使用が完了し、システム資源を節約するために、Workerを閉じなければなりません.
    //    
    worker.terminate();
    
    // Worker   
    self.close();
    
  • データ通信
  • マスタスレッドとWorkカーとの間の通信内容は、テキストであっても良いし、オブジェクトであっても良い.なお、このような通信は、発信元ではなくコピー関係であり、ワーカーが通信内容に対して修正したものであり、主スレッドに影響を与えない.実際、ブラウザ内部の動作メカニズムは、まず通信内容をシリアル化し、シリアル化した文字列をWorkカーに送り、後者は元に戻すことです.メインスレッドとワーカーの間では、File、Blob、ArayBufferなどのバイナリデータを交換しても良いし、スレッド間で送信しても良いです.しかし、コピー方式でバイナリデータを送信すると、性能に問題があります.例えば、メインストリームはWorkカーに500 MBのファイルを送信します.デフォルトではブラウザは元のファイルのコピーを作成します.この問題を解決するために、JavaScriptは、メインスレッドがバイナリデータを直接にサブスレッドに転送することを許可していますが、一旦移行すると、メインスレッドはこれらのバイナリデータをもう使えなくなります.このようなデータの転送方法は、Transferable Objectsといいます.これにより、メインスレッドが速くWorkカーにデータを渡すことができ、映像処理、音声処理、3 D演算などに便利になり、性能に負担がかかりません.
  • データの制御権を直接移行するには、次のような書き方が必要です.
    // Transferable Objects   
    worker.postMessage(arrayBuffer, [arrayBuffer]);
    
    //   
    var ab = new ArrayBuffer(1);
    worker.postMessage(ab, [ab]);
    
  • 一般的なAPI
  • メインスレッドにおけるAPI:
  • error:メインラインからワーカースレッドにメッセージを送る.メッセージは、バイナリデータ
  • を含む任意のタイプのデータであってもよい.
  • worker.postMessage:メインスレッドがワーカースレッドを閉じる
  • worker.terminate:ワーカースレッドがメッセージを送るときのコールバックを指定しても良いし、worker.onmessageの方式で
  • worker.addEventListener('message',cb):ワーカースレッドにエラーが発生した場合のコールバックを指定しても良いし、worker.onerror
  • Workカースレッド内のAPI:
  • worker.addEventListener('error',cb):ワーカースレッドからメインラインのプログラムにメッセージを送信し、メッセージは、バイナリデータ
  • を含む任意のタイプのデータであってもよい.
  • self.postMessage:ウォーカースレッドが自分を閉じている
  • self.close:メインラインプログラムがワーカースレッドメッセージを送信する場合のコールバックを指定しても良いし、self.onmessage
  • self.addEventListener('message',cb):ワーカースレッドにエラーが発生した場合のコールバックを指定しても良いし、self.onerror
  • 実戦シーン
  • ポーリングは、ブラウザがサーバ状態をポーリングする必要があり、状態の変化を最初に知るために必要である.この仕事はワーカーの中に置いてもいいです.
    function createWorker(f) {
      var blob = new Blob(['(' + f.toString() +')()']);
      var url = window.URL.createObjectURL(blob);
      var worker = new Worker(url);
      return worker;
    }
    
    var pollingWorker = createWorker(function (e) {
      var cache;
    
      function compare(new, old) { ... };
    
      setInterval(function () {
        fetch('/my-api-endpoint').then(function (res) {
          var data = res.json();
    
          if (!compare(data, cache)) {
            cache = data;
            self.postMessage(data);
          }
        })
      }, 1000)
    });
    
    pollingWorker.onmessage = function () {
      // render data
    }
    
    pollingWorker.postMessage('init');
    
  • 暗号化されたデータは、復号されたアルゴリズムが複雑であったり、多くのデータを復号する際に、計算リソースが非常に消費され、UIスレッドが応答しなくなるので、これはウェブワーカーを使用する良い機会であり、Workerスレッドを使用することで、ユーザがよりシームレスにUIを行うことができる.
  • プリフェッチデータは、データローディング速度を上げるために、Workカースレッドを使ってデータを取得することができます.
  • は、いくつかのレンダリングシーンにおいて、例えば、複雑なcanvasをレンダリングする際に計算する効果、例えば反射、屈折、光影、材料などを必要とし、これらの計算の論理は、Workerスレッドを使用して実行しても良いし、複数のWorkerスレッドを使用しても良い.
  • 複合データ処理シーンによっては、検索、並べ替え、フィルタリング、分析に時間がかかります.この場合は、Web Workerを使用して行うことができ、メインスレッドを占有しません.
  • プリロードされた画像は、一つのページに多くの画像があり、またはいくつかの大きな画像がある場合、業務制限が怠惰なロードを考慮しない場合、Web Workerを使って画像をロードすることもできます.
    //    
    let w = new Worker("js/workers.js");
    w.onmessage =
      function (event) {
        var img = document.createElement("img");
        img.src = window.URL.createObjectURL(event.data);
        document.querySelector('#result').appendChild(img);
      };
    // worker  
    let arr = [...    ];
    for (let i = 0, len = arr.length; i < len; i++) {
      let req = new XMLHttpRequest();
      req.open('GET', arr[i], true);
      req.responseType = "blob";
      req.setRequestHeader("client_type", "DESKTOP_WEB");
      req.onreadystatechange = () => {
        if (req.readyState == 4) {
          postMessage(req.response);
        }
      };
      req.send(null);
    }
    
  • 注意事項
  • ウォーカースレッドはメインスレッドを占有しませんが、ウォーカーを起動すると比較的リソースがかかります.
  • メインスレッドでは、XMLttpRequestを使用して要求過程において、ブラウザが別の非同期http要求スレッドを開いていますが、インタラクション過程においては、やはりメインスレッドリソース
  • を消費します.
  • 参照リンク
  • MDN-Web Workers概念と用法
  • 阮一峰-Web Worket
  • JavaScript作動原理の7-Web Workers分類及び5つの使用シーン
  • Web Workカープロジェクトの中の妙味
  • どうやってES 6+WebpackでWeb Worker
  • を使いますか?