どうせ疑似的に並列処理するだけかと思ったら、本当にできたので一応メモ。
やったこと
入力した内容をリアルタイムにDeflate形式で圧縮しつつ、確認用に復元されたデータも表示する処理。
- Defalteへの圧縮処理は js-deflate を使用
- 画面表示には Sencha Touch を使用
js-deflateによる圧縮・伸張処理を並列で走らせておき、入力内容に変更があればリアルタイムに圧縮・伸張してそれぞれ表示している。
長い文字列を入力しても重くならず、圧縮・伸張処理によって画面が固まらないことまでは確認した。
実装
並列で走らせておくコードを別ファイルに記述し、メッセージを介してやり取りする仕組み。
ウェブ ワーカーの基本 - HTML5 Rocks
http://www.html5rocks.com/ja/tutorials/workers/basics/
別ファイルにせずともBlobを使用すればインラインで記述可能だが、BLob対応していないブラウザで動かなかったので試していない。
メインスクリプト
ここではworker.js
が並列処理されるコードとして、Workerの引数に指定している。
wkCompression = new Worker('worker.js');
// メッセージを受け取った際の処理を定義
wkCompression.onmessage = function(message) {
var data = message.data;
// 処理結果を受けて振り分け
switch (data.event) {
case 'start':
break;
case 'compressed':
// 圧縮されたデータの表示
outcon.setValue(data.data);
break;
case 'complete':
// 伸張されたデータの表示
outdecon.setValue(data.data);
break;
}
};
メッセージをポスト
キー入力があるタイミングで、入力内容をWorker(worker.js)にポストしてやる。
onKeyupInput: function(src) {
var val = src.getValue();
wkCompression.postMessage({data: val});
}
woker.js
このファイルが別スレッドで実行される。
それゆえ以下の要素にはアクセスできないようです。
- DOM(非スレッドセーフ)
- window オブジェクト
- document オブジェクト
- parent オブジェクト
ただしimportScripts
を使用すると外部スクリプトを読み込むことはできるので、
今回はこれを利用してjs-deflateを読み込んでいます。
// キー入力のたびに呼ばれることになる
onmessage = function(message) {
this.importScripts('./lib/rawdeflate.js');
this.importScripts('./lib/rawinflate.js');
this.importScripts('./lib/base64.js');
// 開始を伝える
this.postMessage({event: 'start'});
// 圧縮結果をメッセージ送信(ついでにBase64変換)
var result = result = Base64.toBase64(RawDeflate.deflate(str));
this.postMessage({
event: 'compressed',
data: result
});
// 伸張結果をメッセージ送信
result = RawDeflate.inflate(Base64.fromBase64(result));
this.postMessage({
event: 'complete',
data: result
});
}
ちなみにこの場合、importScripts
は実行のたび読み込まれるので注意。
Ext.ux.WebWorker
ExtJS または Sencha Touchでやる場合は、
プラグインが公開されているのでそちらを利用すればそれなりにきれいに書けます。
Ext.ux.WebWorker Sencha Tool: Other, Plugins — Sencha Market