5歳になる長男が一人でお風呂に入れるようになりました。
チャレンジチャレンジと言いながら。
そうやって大人になっていくんだなぁと、秋の黄昏と共に切なくなった今日この頃です。
さて、今日はタイトルの通り
WebWorkersを使う時Worker側のonmessageにvarを付けるとChromeで動かない
という事象に出くわしたのでメモっときます。
いきさつ
前作ったbase64 encoderを久々に見てみたら、chromeで動かない。safariでは動く。IE10でも動く。
なんぞこれだったので、ちょっとソースを見直してみた。
2015-10-08 追記
確認した所、IE10、IE11も動きませんでした。。下記でChromeだけ動かないって書いている箇所は全てIE10、IE11も該当します。Chrome様ごめんちゃい。
動かなくなってた原因
原因はちょっと腑に落ちないんだけど、Web Workersを使う時worker側に書くonmessage関数をvarつきで宣言していたからっぽい。※タイトルの通りです。何度もすいません。
動かなかったworker
var onmessage = function(e) { // do something... };
動いたworker
onmessage = function(e) { // do something... };
前にweb workersを試した時、chrome ver.27 で確かに動いていたので、現在のver.45までの間に動かなくなった様ですネ。
※直したソースはこちら shimabox/base64Encoder
そもそもWeb Workersって何?
そもそもWeb Workersってなんなのって話ですが、https://developer.mozilla.org/ja/docs/Web/Guide/Performance/Using_web_workersから引用させて頂くと
Web Workers は、Web コンテンツがスクリプトをバックグラウンドのスレッドで実行するためのシンプルな手段です。Worker スレッドは、ユーザインターフェイスを妨げることなくタスクを実行できます。加えて、それらは (responseXML 属性や channel 属性は常に null ですが) XMLHttpRequest を使用して入出力を行うこともできます。生成された Worker は、生成元が指定したイベントハンドラへメッセージを送ることにより JavaScript コードへメッセージを送ることができます (その逆も可能です)。
だそうです。
簡単に言うなら、別スレッドで処理が行えて、さらにメッセージ(データ)のやり取りも出来ちゃうものです。※端折り過ぎ
例えば、重い計算処理を普通にやっていたら画面が固まってしまいますが、Workerを上手く使うと画面が固まらずに重い計算処理を得る事が出来たりします。
※DOMとかは触れなかったりするので大量の計算結果などを描画する時はさすがに固まったりします
簡単な検証スクリプト
Webを漁れば腐るほどサンプルはありますが、一応自分でもサンプルを書いてみました。
Web Workers を使って素数を数える
※ソースはこちら shimabox/sample_count_prime_using_webworkers
これを試して頂くと、Web Workersを使うを選択して実行した時はgifのローディング画像が動きつつ、他のUIを選択出来たりしますが、Web Workersを使わないを選択して実行した時は画面が固まると思います。
※10,000,000くらいにしたら分かりやすいかも
※計算結果の描画時はWeb Workersを使っててもUIが固まります
PC版Chrome(ver.45) だと動かない
で、一番の問題が、Web Workersを使うけどchrome(PC, Ver.45)だと動かないを選択して実行した時で、chrome(PC, Ver.45)だと動きません。
※これは冒頭に書いた通り、Worker側のonmessageをvar付きで書いたものを読み込んでいます
Workerに対してpostMessage()
をしても、Workerのonmessage()
が呼ばれていない → つまり、WorkerのpostMessage()
も実行されない → 呼び出し元のpostMessage()
も呼ばれないので処理が終わらない状態です。
この現象は自分ではPC版Chrome(ver.45)、IE10、IE11で確認出来ました。
Safari(iOS9も), Firefox, IE10ではvar付きでも動きます。
Web Workersは別スレッドだから、Chromeの場合、varをつけるとスコープ?が変わっちゃうんでしょうかねぇ。。う~~ん、わけわからんです。
で、何が一番納得いかないって、Chromeだけ動かないってところ。
確かに巷に溢れているサンプルを見るとWorker側のonmessage関数はvar無し(global)で宣言されているものが多いけど、var付きでも動くブラウザはあるわけです。
挙動を統一して欲しいどすわ。
まとめ
- Web Workersを使う時Worker側のonmessageはglobal(var無し)で宣言すればとりあえず動く
- Worker側のonmessageはglobalで宣言するのが正しいのかどうか誰か教えて
- var付きのonmessageだとChromeだけ動かなくなるのはどうしてなのか誰か教えて
2015-10-08 追記(最後にもう一度)
確認した所、var付きのonmessageはIE10、IE11も動きませんでした。。Chrome様ごめんちゃい。