SharedWorkerの簡単な例

來源:互聯網
上載者:User

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 は明らかに不要なので、どこかのタイミングで消してあげたい。これを簡単にやる方法は、今のところないっぽい。

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

  • http://lists.whatwg.org/pipermail/whatwg-whatwg.org/2010-March/025543.html

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.