ホームページ >ウェブフロントエンド >htmlチュートリアル >Web ワーカーについて知っておくべき 7 つのこと
Web ワーカーを使用すると、Web ユーザー インターフェイスをブロックせずに JavaScript コードをバックグラウンドで実行できます。 Web ワーカーは、Web ページの全体的なパフォーマンスを向上させ、ユーザー エクスペリエンスも向上させることができます。 Web ワーカーには、専用 Web ワーカーと共有 Web ワーカーの 2 種類があります。この記事では、アプリケーションで Web ワーカーを使用するかどうかを決定するために知っておく必要がある、Web ワーカーの 7 つの重要な側面について説明します。
通常、Web ページに記述した JavaScript コードは、ユーザー インターフェイスと同じスレッドで実行されます。これが、長いプロセスを引き起こすボタンをクリックすると Web ページのユーザー インターフェイスがフリーズする理由です。処理が完了するまで、ユーザー インターフェイスで作業することはできません。 Web ワーカーを使用すると、JavaScript をバックグラウンドで実行できるため、いくつかのスクリプトが同時に実行されている場合でも、ユーザー インターフェイスの応答性が維持されます。スクリプトを実行するバックグラウンド スレッドは、ワーカー スレッドまたはワーカーと呼ばれることがよくあります。必要なだけワーカーを生成できます。ワーカー スレッドで実行中のスクリプトにデータを渡し、完了時に値をメイン スレッドに返すこともできます。ただし、Web Workers には次のようないくつかの制限があります:
Web ワーカーは Web ページから DOM 要素にアクセスできません。
Web ワーカーは、Web ページからグローバル変数や JavaScript 関数にアクセスできません。
Web ワーカーは、alert() 関数またはconfirm() 関数を呼び出すことができません。
Web Workers では、ウィンドウ、ドキュメント、親などのオブジェクトにアクセスできません。
ただし、setTimeout()、setInterval() などの関数は使用できます。 XMLHttpRequest オブジェクトを使用して、サーバーに対して Ajax リクエストを行うこともできます。
Web ワーカーには、専用 Web ワーカーと共有 Web ワーカーの 2 種類があります。専任の Web ワーカーは、自分たちを作成する Web ページとともに生き、そして死んでいきます。これは、Web ページ内で作成された専用 Web ワーカーには、複数の Web ページ間でアクセスできないことを意味します。一方、共有 Web ワーカーは、複数の Web ページ間で共有されます。 Worker クラスは専用の Web ワーカーを表し、SharedWorker クラスは共有 Web ワーカーを表します。
多くの場合、専任の Web ワーカーがお客様のニーズに応えます。これは、通常、Web ページの特定のスクリプトをワーカー スレッドで実行する必要があるためです。ただし、場合によっては、複数の Web ページに共通のワーカー スレッドでスクリプトを実行する必要があります。この場合、各ページに 1 つずつ、多数の専用 Web ワーカーを作成する代わりに、共有 Web ワーカーを使用することもできます。 1 つの Web ページで作成された共有 Web ワーカーは、他の Web ページでも引き続き使用できます。すべての接続が閉じられている場合にのみ破棄できます。共有 Web ワーカーは、専用 Web ワーカーよりも少し複雑です。
Web ワーカーの基本を理解したところで、専用の Web ワーカーの使用方法を見てみましょう。以下で説明する例では、お気に入りの開発ツールを使用して Web アプリケーションを作成し、その Script フォルダーに jQuery ライブラリと Modernizr ライブラリを追加していることを前提としています。 HTML ページを Web アプリケーションに追加し、次のコードを入力します:
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title></title> <script src="scripts/modernizr.js"></script> <script src="scripts/jquery-2.0.0.js"></script> <script type="text/javascript"> $(document).ready(function () { if (!Modernizr.webworkers) { alert("This browser doesn't support Web Workers!"); return; } $("#btnStart").click(function () { var worker = new Worker("scripts/lengthytask.js"); worker.addEventListener("message", function (evt) { alert(evt.data); },false); worker.postMessage(10000); }); }); </script> </head> <body> <form> <input type="button" id="btnStart" value="Start Processing" /> </form> </body> </html>
上記の HTML ページには、JavaScript 処理をトリガーするボタン (btnStart) が含まれています。このページは、Modernizr ライブラリと jQuery ライブラリを参照していることに注意してください。 3f1c4e4b6b16bbbd69b2ee476dc4f83a ブロックには、ready() メソッド ハンドラーが含まれており、このハンドラーは btnStart のクリック イベントを処理します。 ready() ハンドラーは、まずブラウザーが Web ワーカーをサポートしているかどうかを確認します。これは、Modernizr の webworkers プロパティを使用して行われます。ブラウザが Web ワーカーをサポートしていない場合は、エラー メッセージがユーザーに表示されます。
次に、コードは btnStart のクリック イベント ハンドラーに接続します。クリック イベント ハンドラーのコードは、Worker オブジェクトを使用してバックグラウンドでスクリプトを実行するため、重要です。クリック イベント ハンドラーは Worker オブジェクトを作成し、それをローカル変数 worker に保存します。バックグラウンドで実行される JavaScript ファイルへのパスはコンストラクターに渡されます。すぐに LengthyTask.js が作成されます。次に、コードは Worker オブジェクトのメッセージ イベントのイベント ハンドラーを追加します。メッセージ イベントは、ターゲット スクリプト (この場合は LengthyTask.js) がいくつかの値を Web ページに送り返すときに発生します。メッセージ イベント ハンドラーは、evt.data プロパティを使用して戻り値にアクセスできます。最後に、Worker オブジェクトに対して postMessage() メソッドが呼び出され、LengthyTask.js の実行がトリガーされます。 postMessage() メソッドを使用すると、ターゲット スクリプトにデータを渡すこともできます。この例では、数値 (10000) が postMessage() に渡され、処理が継続するミリ秒数を示します。 postMessage() 呼び出しでは、JavaScript オブジェクトや文字列などの他のデータを渡すことができます。
以下に示すように、LengthyTask.js ファイルには、バックグラウンドで実行されるコードが含まれています。
addEventListener("message", function (evt) { var date = new Date(); var currentDate = null; do { currentDate = new Date(); } while (currentDate - date < evt.data); postMessage(currentDate); }, false);
上面的代码处理worker thread的消息事件。当主页面调用Worker对象上的postMessage()方法时,会引发消息事件。消息事件处理程序通过运行某些毫秒的do-while循环来模拟冗长的处理。此循环运行的毫秒数从主页传递(回忆前面讨论的postMessage())。因此,evt.data在此示例中返回10000。一旦长时间操作完成,代码调用postMessage()会把处理结果发送回主页面。在本例中,传递currentDate的值(currentDate是一个Date对象)。
如果你运行主网页并单击Start Processing按钮,那么你将在10秒后收到alert()。同时,页面的用户界面不会被阻止,你可以执行诸如滚动,点击等操作,表明来自LengthyTask.js的代码正在后台运行。
前面的示例使用了专用Web worker。让我们将同样的示例转换为使用共享Web worker。共享Web worker由SharedWorker对象表示。下面的代码显示了来自主页的代码的修改版本:
$(document).ready(function () { if (!Modernizr.webworkers) { alert("This browser doesn't support Web Workers!"); return; } $("#btnStart").click(function () { var worker = new SharedWorker("scripts/sharedlengthytask.js"); worker.port.addEventListener("message", function (evt) { alert(evt.data); }, false); worker.port.start(); worker.port.postMessage(10000); }); });
注意用粗体字标记的代码。它创建了一个SharedWorker实例,并在构造函数中传递SharedLengthyTask.js。你将很快创建此文件。然后,代码将消息事件处理程序连接到SharedWorker对象的端口对象。消息处理程序函数执行与前面示例中相同的工作。然后代码在端口对象上调用start()方法。最后,在端口对象上调用postMessage()方法将数据(10000)发送到共享worker thread。
SharedLengthyTask.js文件包含以下代码:
var port; addEventListener("connect", function (evt) { port = evt.ports[0]; port.addEventListener("message", function (evt) { var date = new Date(); var currentDate = null; do { currentDate = new Date(); } while (currentDate - date < evt.data); port.postMessage(currentDate); }, false); port.start(); }, false);
代码首先声明一个名为port的变量,用于存储端口对象的引用。这次处理了两个事件——connect和message。当与共享Web worker建立连接时,会触发connect事件。 connect事件处理程序捕获evt.port [0]对象并将其存储在之前声明的端口变量中。然后在端口对象上连接消息事件处理程序。调用端口对象的start()方法来开始侦听该端口上的消息。消息事件处理程序几乎与你在前面的示例中编写的消息事件处理程序相同,除了它附加到端口对象这一点。此外,在端口对象上调用postMessage(),以将处理结果发送到主页面。
有时Web Worker可能需要与Web服务器通信。例如,你可能需要驻留在某些RDBMS中的数据以便于客户端处理。要完成此类任务,你可以使用XMLHttpRequest对象向服务器端资源发出请求。实例化Worker对象和处理消息事件的整个过程保持不变。但是,你需要向服务器端资源发出GET或POST请求。考虑下面的代码:
addEventListener("message", function (evt) { var xhr = new XMLHttpRequest(); xhr.open("GET", "lengthytaskhandler.ashx"); xhr.onload = function () { postMessage(xhr.responseText); }; xhr.send(); }, false);
上面显示的代码创建了XMLHttpRequest对象的实例。然后调用open()方法,并指定向服务器端资源LengthyTaskHandler.ashx(一个ASP.NET通用处理程序)发出GET请求。(虽然此示例使用ASP.NET通用处理程序,但你可以使用任何其他服务器端资源。)然后它处理XMLHttpRequest对象的load事件并调用postMessage()。 xhr.responseText作为postMessage()的参数。xhr.responseText将是ASP.NET通用处理程序作为响应返回的值。请求完成时引发load事件。
LengthyTaskHandler.ashx包含以下代码:
namespace WebWorkersDemo { public class LengthyTaskHandler : IHttpHandler { public void ProcessRequest(HttpContext context) { System.Threading.Thread.Sleep(10000); context.Response.ContentType = "text/plain"; context.Response.Write("Processing successful!"); } public bool IsReusable { get { return false; } } } }
正如你可以看到,ProcessRequest()通过在Thread类上调用Sleep()方法来模拟一些冗长的处理,并阻止执行10秒。然后它返回一个成功消息“Processing successful!”给调用者。如果你在进行这些更改后运行主网页,你会发现在10秒后,将显示一个包含此成功消息的警报对话框。
如果你的Web worker正在进行一些复杂的操作,那么你可能需要添加错误处理到主网页代码,以便在worker中出现任何未处理错误时,可以采取适当的操作。这可以通过处理Worker对象的错误事件来完成。每当work thread中存在任何未处理的错误时,就会抛出错误事件。以下代码显示了如何完成此操作:
$("#btnStart").click(function () { var worker = new Worker("scripts/lengthytask.js"); worker.addEventListener("message", function (evt) { alert(evt.data); }, false); worker.addEventListener("error", function (evt) { alert("Line #" + evt.lineno + " - " + evt.message + " in " + evt.filename); }, false); worker.postMessage(10000); });
从上面的代码可以看出,错误处理程序已经连接到worker对象的错误事件。错误处理函数接收一个事件对象,而该对象提供错误信息,例如发生错误的行号(evt.lineno),错误消息(evt.message)和发生错误的文件(evt.filename)。
ワーカーで実行中のタスクをキャンセルしたい場合があります。このために、ワーカーの terminate() メソッドを呼び出してワーカーを破棄できます。ワーカーを終了すると、再利用または再起動することはできません。もちろん、いつでも別の Worker インスタンスを作成して使用できます。ただし、terminate() はワーカーを即座に強制終了し、クリーンアップ操作を実行する機会を与えないことに注意してください。
Web ワーカーを使用すると、Web ユーザー インターフェイスをフリーズさせることなく、バックグラウンドでスクリプトを実行できます。専用 Web ワーカーと共有 Web ワーカーの 2 つのタイプがあります。 Web ページごとに専用の Web ワーカーを作成し、複数の Web ページ間で共有するには共有 Web ワーカーを使用します。 Worker クラスは専用 Web ワーカーを表し、SharedWorker クラスは共有 Web ワーカーを表します。この記事では、両方のタイプの使用方法について説明し、エラーの処理方法と、Web ワーカーが XMLHttpRequest を使用して Web サーバーと通信する方法についても説明します。
以上がWeb ワーカーについて知っておくべき 7 つのことの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。