More than 1 year has passed since last update.

JSで非同期処理をする際に便利なインラインワーカーですが、ワーカーは通常ブラウザjsとは別のグローバルスコープで実行されるため、型付のHaxeでは使用するのがちょっと面倒でした。

インラインワーカーについてはこちらの記事を参考にしています。

http://qiita.com/mohayonao/items/872166cf364e007cf83d

https://developer.mozilla.org/ja/docs/Web/Guide/Performance/Using_web_workers

WorkerUtil.hx
class WorkerUtil {
    static var reg = new RegExp("^function\\s*\\w*\\s*\\([\\w\\s,]*\\)\\s*{([\\w\\W]*?)}$", "i");
    public static function createInlineWorker(workerFunc: Dynamic): Worker {
        var func = workerFunc.toString().trim().match(reg)[1];
        var blob = new Blob([ func ], { type: "text/javascript" });
        var url = URL.createObjectURL(blob);
        return new Worker(url);
    }
}

Main.hx

var worker = WorkerUtil.createInlineWorker(function() {
    var global: DedicatedWorkerGlobalScope = js.Lib.eval("self");
    global.onmessage = function(m: MessageEvent) {
        global.postMessage(m.data+"!!");
    };      
});
worker.onmessage = function(m: MessageEvent) {
    trace(m.data); // Hello World!!
}
worker.postMessage("Hello World");


当初、通常のjsのように、ワーカーで実行される無名関数内のスコープが実行時ワーカースコープになるという特徴をどうHaxeで実現するか悩んだのですが、結果的に、 JavaScriptのevalが常にグローバルスコープで評価される という特徴を思い出し、eval("self")をすればいいと気がつきました。WebWorkerのグローバルスコープには上記のMDNのようないくつかの関数と変数が登録されており、それらはWorkerGlobalScopeというインラーフェースとしていくつかの実装系があります。通常のWebWorkerの場合、DedicatedWorkerGlobalScopeというクラスになるため、selfの値はそのインスタンスになります。なので、このような形で書くことによってHaxeのコンパイラのエラーを回避できます。