- 2015/01/14
- HTML5minutes! - triton-js @ Members Co., Ltd.
- Seiya Konno
- Works at Uniba Inc. (http://uniba.jp)
__月刊ライトニングトーク__というウェブ系の勉強会を主催しています。
今のところだいたい隔月で開催中。場所は渋谷か上野でやることが多いです。
Web Worker 使ってますか?
- UI のイベントループとは独立したイベントループで処理を実行
- OS のスレッドを使って実行
- CPU bound な処理でも UI をブロックしない
- 独立したスコープで処理を実行
- UI 側のグローバルオブジェクトにアクセスできない
- Worker 側でグローバル汚染しても UI 側に影響されない
- DOM にアクセスすることができない
- 代表的なユースケース
- 巨大な JSON ファイルのシリアライズ
- Canvas の
ImageData
のピクセル操作 - ゲームなど FPS が重要なコンテンツの開発
- main.js: メインスレッドから Worker を生成
var worker = new Worker('worker.js');
// worker からのメッセージを受信
worker.onmessage = function(e) {
console.log(e.data); // 1: HELLO
// 2: HELLO
// 3: HELLO ...
};
setInterval(function() {
// worker へメッセージを送信
worker.postMessage('hello');
}, 1000);
- worker.js: 受け取ったデータを大文字に変換して返却
var count = 0;
// 生成元からのメッセージを受信するためのイベントリスナ
self.onmessage = function(e) {
count++;
// 生成元へメッセージを送信
self.postMessage(count + ': ' + e.data.toUpperCase());
};
図にまとめると...
Worker 側のコードを別ファイルにしなければならない。
- 気軽に Web Developer Console で試せない
- タスクランナーで concat + minify したときの恩恵が受けられない
- Browserify で worker 側のコードを
require
したい
こんな風にインラインでかければいいのに。
var worker = new Worker(function() {
var count = 0;
self.onmessage = function(e) {
count++;
self.postMesage(count + ': ' + e.data.toUpperCase());
};
});
worker.onmessage = function(e) {
console.log(e.data);
};
setInterval(function() {
worker.postMessage('hello');
}, 1000);
pseudo-function
というライブラリをつくりました。
さっきのサンプルがインラインっぽく書けるようになります。
var fn = new PseudoFunction(function() {
var count = 0;
self.onmessage = function(e) {
count++;
self.postMessage(count + ': ' + e.data.toUpperCase());
};
});
var worker = new Worker(fn);
worker.onmessage = function(e) {
console.log(e.data);
};
setInterval(function() {
worker.postMessage('hello');
}, 1000);
- 関数オブジェクトから
URL.createObjectURL
で Blob URL を生成 - Blob URL は
Blob
オブジェクトを外部ファイルのように扱える - 上記の特徴を利用して
Worker
のコンストラクタに Blob URL を渡すことでインラインで記述可能
- IE 11+, Firefox 12+, Chrome 26+, Safari 6+, Android 4.4+ に対応
- Bower に対応 (
$ bower install pseudo-function
) - Browserify に対応 (
$ npm install pseudo-function
) - Component, Duo にも対応 (
require('nulltask/pseudo-function')
) - ユニットテスト付属、Travis CI でテストを実行
- MIT ライセンス (商用利用に制限なし)
pseudo-function
を使って作った stable-timer
というライブラリ。
どんな状況でも安定して動作するタイマー。
Worker 内の setTimeout
, setInterval
は生成元のタブやブラウザそのものがバックグランドに回っても分解能が変わらない特性を利用。
Worker 用のコードをインラインで記述しているため、ライブラリのユーザが意識しなくとも Web Worker による処理を利用できるようになった。
ご静聴ありがとうございました。