• SharedWorkerの簡単な例


    SharedWorker について、仕様にある例は大きすぎて何が起こってるのかつかみにくいので、簡単な例を載せてはどうか、というメールがあったので紹介。

    僕も SharedWorker は例が面倒なので今日までちゃんと読んだことがなかった。


    簡単な順に3段階。


    step 1

    • test.html
     
    <pre id="log">Log:</pre> 
    <script> 
    var worker = new SharedWorker('test.js'); 
    var log = document.getElementById('log'); 
    worker.port.onmessage = function(e) { // note: not worker.onmessage! 
       log.textContent += '\n' + e.data; 
    } 
    </script> 
    
    • test.js
     
    onconnect = function(e) { 
       var port = e.ports[0];
       port.postMessage('hello');
    } 
    

    test.html を開くと test.js が SharedWorker として呼ばれる。

    普通の Worker と違って worker.port.onmessage で通信するらしい。

    test.js のほうで var port = e.ports[0] とやっているのは、MessageChannel のほうに詳しく書いた。

    ただしそこは var port = e.target でもいいらしい。


    step 2

    • test.html
     
    <pre id="log">Log:</pre> 
    <script> 
    var worker = new SharedWorker('test.js'); 
    var log = document.getElementById('log'); 
    worker.port.addEventListener('message', function(e) { 
       log.textContent += '\n' + e.data; 
    }, false); 
    worker.port.start(); // note: need this when using addEventListener 
    worker.port.postMessage('ping'); 
    </script> 
    
    • test.js
     
    onconnect = function(e) { 
       var port = e.ports[0];
       port.postMessage('hello');
       port.onmessage = function(e) { 
         port.postMessage('pong'); // not e.ports[0].postMessage! 
       } 
    } 
    

    worker.port.onmessage をセットすると暗黙の了解で Worker スレッドを走らせてくれるけど、addEventListener('message',..) の場合は start() を明示的に呼んでやらないといけない。

    The first time a MessagePort object's onmessage IDL attribute is set, the port's port message queue must be enabled, as if the start() method had been called.

    http://www.w3.org/TR/html5/comms.html#messageport

    step 3

    • test.html
     
    <pre id="log">Log:</pre> 
    <script> 
    var worker = new SharedWorker('test.js'); 
    var log = document.getElementById('log'); 
    worker.port.addEventListener('message', function(e) { 
       log.textContent += '\n' + e.data; 
    }, false); 
    worker.port.start(); 
    worker.port.postMessage('ping'); 
    </script> 
    <iframe src=other.html></iframe> 
    
    • other.html
     
    <pre id=log>Inner log:</pre> 
    <script> 
    var worker = new SharedWorker('test.js'); 
    var log = document.getElementById('log'); 
    worker.port.onmessage = function(e) { 
       log.textContent += '\n' + e.data; 
    } 
    </script> 
    
    • test.js
     
    var i = 0;
    onconnect = function(e) { 
       i++;
       var port = e.ports[0];
       port.postMessage('hello, ' + i);
       port.onmessage = function(e) { 
         port.postMessage('pong');
       } 
    } 
    

    test.html と other.html から同じ URL の SharedWorker が呼び出され、それらは共有される。どちらかを開いたままもう一方をリロードすると、数字が増えていくはず。


    感想

    何に使えるか。たしか Chrome のドキュメントのどこかで、Gmail のようなアプリケーションでタブを複数開くと、それぞれが独立にサーバーと通信して面倒なことになるので、セッションをまとめる役割で使えるとか読んだ気がする。

    普通の Worker だったら単にグローバルに onmessage = function() ... と書くところを、onconnect = function(e) { e.ports[0].onmessage = ...} として port を自分で収集しないといけないらしい。大変気持ち悪い。

    例えば step 3 の場合、test.html と other.html を両方開いた状態で片方をリロードすると、そのたびに var port = e.ports[0] されて port.onmessage = function(e) { port.postMessage('pong'); } が呼ばれることになるけど、そのぶんのメモリはいつ解放されるんだろう。たぶん全部の親ウィンドウを閉じたときに Worker ごと消える? だったら適当な間隔で port が繋がっているかを監視する必要があると思うんだけど、isConnected のようなプロパティは無いみたいだし、実際に送ってみないと相手が存在するか分からないようになっているっぽい。

    Hixie さん曰く、上のケースでは適切に解放されるらしい。下のケースでは手動で解放しないといけないらしい。

    別の例を考えてみる。以下のような Shared Worker Script があったとして、

     
    var myPorts = [];
     
    onconnect = function(e) { 
      var port = e.ports[0];
      myPorts.push(port);
     
      port.onmessage = function(e) { // あるタブからメッセージを受け取ったら 
        myPorts.forEach(function(p) { 
          if (p !== port)
            p.postMessage(e.data); // 他のすべてのタブに同じメッセージを送る 
        });
      } 
    } 
    

    複数の親タブのうちの一つがリロードされたとする。すると、myPorts がどんどん増えていくことになる。だけど、リロードされる前のタブと繋がっている port は明らかに不要なので、どこかのタイミングで消してあげたい。これを簡単にやる方法は、今のところないっぽい。

    このへんは気が向いたらメールを投げてみようと思う。↓メールした。

  • 相关阅读:
    shell基础优化脚本
    shell的常用脚本一
    Office/Visio/Project 2019 专业版iso
    vs2017 不能加载.vdproj
    CA机构及SSL证书
    singleWsdl和wsdl区别,Axis2和CXF对比
    在Window Server 2016中使用Web Deploy方式发布.NET Web应用
    NPOI导出excel
    audio隐藏下载按钮
    网站崩溃,如果提高网站并发能力
  • 原文地址:https://www.cnblogs.com/rubylouvre/p/1715078.html
  • Copyright © 2020-2023  润新知