HTML5 は Web Worker などの API をサポートしており、Web ページでマルチスレッド コードを安全に実行できるようになります。しかし、実際にはWeb Workerには多くの制限があり、メモリデータを完全に共有することはできず、ステータス通知もメッセージでしか行えないため、本当の意味での「マルチスレッド」とは言えません。
Web Worker のインターフェースは、基本的にサンドボックスが付属しており、サンドボックス内で独立した js ファイルを実行し、postMessage および onMessage を通じてメインスレッドと通信します。
得られた結果は、スレッド内で取得したデータのIDが増加していることがわかりますが、それが返された後、メインスレッドのバンドル内のIDは変化していないため、スレッドに渡されたオブジェクトが返されます。実際にはコピーされるため、その場合、スレッドはデータを共有せず、読み取りと書き込みの競合を回避できるため、安全です。スレッドの安全性を確保する代償として、スレッド内のメイン スレッド オブジェクトを操作する機能が制限されます。
このような制限されたマルチスレッド メカニズムは、使用するのが非常に不便です。たとえば、次のようなコードをサポートしているように Worker がサポートできることを期待しています。以下:
worker.run(function(bundle){
// ワーカースレッドで sth を実行します...
This.runOnUiThread(function(bundle /*shared obj*/){
// メイン UI スレッドで sth を実行します...
});
//...
});
このコードでは、ワーカーを開始した後、ワーカー内で任意のコードを実行でき、UI スレッドを操作する必要があるとき (DOM の読み取りと書き込みなど)、メイン スレッドに戻って実行できます。 this.runOnUiThread を通じて。
では、このメカニズムを実装するにはどうすればよいでしょうか? 以下のコードを見てください:
var self = this;
This._worker.onmessage = function(evt){
var ret = evt.data;
If(ret.__UI_TASK__){
// ui タスクで実行
var fn = (new Function("return " ret.__UI_TASK__))();
fn(ret.sharedObj);
}その他{
self.sharedObj = ret.sharedObj;
self._completes[ret.taskId](ret);
}
}
}
WorkerThread.prototype.run = function(タスク、完了){
var _task = {__THREAD_TASK__:task.toString()、sharedObj: this.sharedObj、taskId: this._task_id};
This._completes[this._task_id ] = 完了;
This._worker.postMessage(_task);
}
上記のコードは、Thread.js を実行する Web ワーカーを作成し、共有オブジェクト SharedObj を保存し、thread.js によって返されたメッセージを処理する ThreadWorker オブジェクトを定義します。
thread.js から UI_TASK メッセージが返された場合は、メッセージによって渡された関数を実行します。それ以外の場合は、run の完全なコールバックを実行します。thread.js の記述方法を見てみましょう。
if(データ && データ.__THREAD_TASK__){
var task = data.__THREAD_TASK__;
試してみましょう{
var fn = (new Function("return " task))();
var ctx = {
threadSignal: true、
スリープ: 関数(間隔){
ctx.threadSignal = false;
setTimeout(_run, interval);
},
runOnUiThread: function(タスク){
PostMessage({__UI_TASK__:task.toString(),sharedObj:data.sharedObj});
}
}
関数 _run(){
ctx.threadSignal = true;
var ret = fn.call(ctx, data.sharedObj);
PostMessage({error:null, returnValue:ret, __THREAD_TASK__:task,sharedObj:data.sharedObj, taskId:data.taskId});
}
_run(0);
}キャッチ(例){
PostMessage({error:ex.toString(), returnValue:null,sharedObj: data.sharedObj});
}
}
}
ご覧のとおり、thread.js は ui スレッドからメッセージを受け取ります。その中で最も重要なものは THREAD_TASK です。これは、関数以降、ui スレッドによって渡され、ワーカー スレッドによって実行される必要がある「タスク」です。渡されるのは文字列です。ワーカー スレッドは文字列を関数に解析して、メイン スレッドによって送信されたタスクを実行します (実行完了後、共有オブジェクトsharedObj がタスクに渡されることに注意してください)。返された結果は、メッセージを通じて ui スレッドに渡されます。詳しく見てみましょう。戻り値 returnValue に加えて、共有オブジェクトsharedObjも返されます。これは、ワーカー スレッドと ui スレッドがオブジェクトを共有していないため、両方のオブジェクトを人工的に同期させます。割り当て (このスレッドは安全ですか? ? なぜですか? )
この実装後、この ThreadWorker は次の 2 つの方法で使用できることがわかります。
setInterval(function(){
t1.run(function(sharedObj){
戻りsharedObj.i ;
}、
関数(r){
console.log("t1>" r.returnValue ":" r.error);
}
);
}, 500);
var t2 = 新しい WorkerThread({i: 50});
t2.run(function(sharedObj){
while(this.threadSignal){
共有オブジェクト;
this.runOnUiThread(function(sharedObj){
W("body ul").appendChild("
this.sleep(500);
}
戻りsharedObj.i;
}、関数(r){
console.log("t2>" r.returnValue ":" r.error);
});
このような使用方法は、形式と説明の両方から、良好な構造、電気活性、および耐久性を備えていると考えられます。
よろしくお願いします。Web Worker の使用法探索については、ここにアクセスします。興味のある同学は次のこの項目を参照してください: https://github.com/akira-cn/WorkerThread.js (Worker が必要なサービスの調査のため) 、私は特に、非常に厳格な http サービスの js である 1 つの山に httpd.js を配置しました。ノードから直接接続できます)。