JavaScriptこの言語はシングルスレッドモデル、つまりすべてのタスクを使用しますqueue は一度に 1 つのことしか実行できませんが、コンピューターの処理能力が向上すると、JavaScript の可能性を十分に発揮できなくなります。ローカル ファイルを読み取る場合はさらに当てはまります。Web Worker の目的は、JavaScript 用のマルチスレッド環境を作成し、メイン スレッドの実行中にメイン スレッドが一部のタスクをサブスレッドに割り当てられるようにすることです。この 2 つはバックグラウンドで相互に干渉しません。サブスレッドが計算タスクを完了すると、結果がメインスレッドに返されます。したがって、各サブスレッドは静かに作業を完了します。 Web Worker には次のような機能があります:
同一ドメイン制限: サブスレッドによってロードされるスクリプト ファイルは、メイン スレッドのスクリプト ファイルと同じドメインに存在する必要があります。サブスレッドは、制限された Web ページの DOM オブジェクトを読み取ることはできません。つまり、 document 、 window、および親オブジェクトは、サブスレッドによって取得できません (ただし、navigator オブジェクトと location オブジェクトは取得できます)。
スクリプトの制限: サブスレッドは、Web ページのグローバル変数や関数を読み取ることも、アラートや確認メソッドを実行することもできませんが、setInterval と setTimeout を実行し、XMLHttpRequest オブジェクトを使用して AJAX リクエストを行うことはできます。new
コマンドを使用して Worker メソッドを呼び出し、新しいサブスレッドを作成します。これは、子スレッドが完了する必要があるスクリプト ファイルです。上記のコードは work.js です。子スレッドはローカル ファイル システムを読み取ることができないため、このスクリプト ファイルはネットワークから取得される必要があります (404 エラーなど)。この子スレッドはサイレントに失敗します。if (window.Worker) { // 支持} else { // 不支持}
postMessage メソッドのパラメータは、メインスレッドから子スレッドに渡されるシグナル。
stringvar worker = new Worker('work.js');
3. サブスレッドの
イベントサブスレッドには、メッセージイベントを監視するためのコールバック関数が必要です。
worker.postMessage('hello world');
selfはサブスレッドそのものを表し、self.addEventListenerはサブスレッドのメッセージイベントに対するコールバック関数を指定することを意味します(onmessage
属性の値を直接指定することもできます)。コールバック
関数のパラメータはイベント オブジェクトであり、その data 属性にはメインスレッドによって送信されたシグナルが含まれます。 self.postMessage は、子スレッドがメインスレッドにシグナルを送信することを意味します。 メインスレッドによって送信されたさまざまなシグナル値に従って、サブスレッドはさまざまなメソッドを呼び出すことができます。
worker.postMessage({method: 'each', args: ['work']});
//File: work.jsself.addEventListener('message', function(e) { self.postMessage('You said: ' + e.data); }, false);
5. エラー処理
メインスレッドは子スレッドでエラーが発生したかどうかを監視できます。エラーが発生すると、メインスレッドのエラーイベントがトリガーされます。 'message', method = args = reply =);
// File: main.jsworker.addEventListener('message', function(e) { console.log(e.data); }, false);
子スレッドで内部的に閉じることもできます。
worker.onerror(function(e) { console.log(e); });// orworker.addEventListener('error', function(e) { console.log(e); }, false);
メインスレッドとサブスレッド間の通信内容はテキストでもオブジェクトでも構いません。この種の通信はコピー関係、つまり、サブスレッドによる通信内容の変更はメインスレッドには影響を与えないことに注意してください。実際、ブラウザの内部動作メカニズムは、まず通信コンテンツをシリアル化し、次にシリアル化された文字列を子スレッドに送信し、子スレッドがそれを復元します。
但是,用拷贝方式发送二进制数据,会造成性能问题。比如,主线程向子线程发送一个500MB文件,默认情况下浏览器会生成一个原文件的拷贝。为了解决这个问题,JavaScript允许主线程把二进制数据直接转移给子线程,但是一旦转移,主线程就无法再使用这些二进制数据了,这是为了防止出现多个线程同时修改数据的麻烦局面。这种转移数据的方法,叫做Transferable Objects。
如果要使用该方法,postMessage方法的最后一个参数必须是一个数组,用来指定前面发送的哪些值可以被转移给子线程。
worker.postMessage(arrayBuffer, [arrayBuffer]);
通常情况下,子线程载入的是一个单独的JavaScript文件,但是也可以载入与主线程在同一个网页的代码。假设网页代码如下:
<!DOCTYPE html> <body> <script id="worker" type="app/worker"> addEventListener('message', function() { postMessage('Im reading Tech.pro'); }, false); </script> </body></html>
我们可以读取页面的script,用worker来处理。
var blob = new Blob([document.querySelector('#workere').textContent]);
这里需要把代码当作二进制数据读取,所以使用Blob接口。然后,这个二进制对象转为URL,再通过这个URL创建worker。
var url = window.URL.createObjectURL(blob);var worker = new Worker(url);
部署事件监听代码。
worker.addEventListener('message', function(e) { console.log(e.data); }, false);
最后启动worker。
worker.postMessage('');
整个页面的代码如下:
<script> (function() { var blob = new Blob([document.querySelector('#worker').textContent]); var url = window.URL.createObjectURL(blob); var worker = new Worker(url); worker.addEventListener('message', function(e) { console.log(e.data); }, false); worker.postMessage(&#39;&#39;); })(); </script>