目標は、次のようにすることを学ぶことです。
new PromiseWorker(array => array.sort()).Invoke([3,2,1]).then(result => console.log(result));
(以下、簡潔にするために矢印関数を使用します)
ご存じのとおり、ワーカーを作成する本当の方法は、ファイルパスを唯一のパラメーターとして渡すことです:
new Worker("/JS/worker.js")
。 onmessageハンドラーを切断し、postmessageを呼び出して、ワーカーファイル内の同様のスタイルに固執します。 私の意見では、1つの関数のファイル全体を作成するのは大胆すぎて、イベントハンドラーをいじることはもはや面倒ではありません。 良いことは、すでに述べたブロブと約束があります。
まず、入力関数をワーカーが受け入れられる形式に変換する必要があります。
var FnToWorker = fn => { var workerBody = "self.addEventListener('message'," + "function (d) {" + "var result;" + "try {" + "result = (" + fn.toString() + ")(d.data.Data);" + "self.postMessage({ Result: result, Id: d.data.Id });" + "} catch (e) {" + "self.postMessage({ Error: e, Id: d.data.Id });" + "}" + "});" var worker = new Worker(URL.createObjectURL(new Blob([workerBody]))); return worker; }
はい、嫌な文字列の連結、fn.toString()、その他のひどいものがあります...主なことは、このコードを一度書くだけでそれを忘れることができるということです。
コメントで指摘したように、この構造にはいくつかの制限があります。関数には外部依存関係(クロージャー変数、ワーカーに許可されていないウィンドウオブジェクト)があってはなりません。 ワーカースレッドからはアクセスできません。 fn.toString()は関数の本体を返さないため、システム関数を使用して作成された関数(Function.prototype.bindなど)はワーカーで使用できません。
Invokeは次のようになります。
var promises = []; // var Invoke = data => { var message = { Data: data, Id: performance.now() }; // Id, var p = new Promise((resolve, reject) => { promises[message.Id] = { resolve: resolve, reject: reject }; }); worker.postMessage(message); // return p; }
Promiseの使用は難しくありません。2つの引数の関数をコンストラクターに渡します:resolveとreject。 これらは、操作が成功した場合と失敗した場合に呼び出す必要がある関数です。 私たちの場合、これらはワーカーが働いた後に呼び出されます:
var OnMessage = data => { if (data.data.Error) { promises[data.data.Id].reject(data.data.Result); } else { promises[data.data.Id].resolve(data.data.Result); } promises[data.data.Id] = undefined; }
さて、それはこのアセンブリのように見えます: http : //jsfiddle.net/sXJ4M/1/
もちろん、オンラインストアで従業員をどこで使用できるか想像することは困難ですが、大規模で複雑なアプリケーションでは多くの人が役立ちます。