関連する無料学習の推奨事項: javascript (ビデオ)
今回は、次のステップを実行します。 Web ワーカー を説明するには、簡単な概念から始めて、さまざまな種類の Web ワーカー とそのコンポーネントがどのように機能するかについて説明します。の連携と、さまざまなシナリオにおけるそれぞれの利点と制限について説明します。最後に、Web Workers を正しく使用するための 5 つのシナリオを示します。
前の記事で説明したように、JavaScript 言語はシングルスレッド モデルを使用していることを知っておく必要があります。ただし、JavaScript は開発者に非同期コードを作成する機会も提供します。
これまでの記事では、非同期プログラミングとそれを使用する必要がある場合について説明しました。
非同期プログラミングにより、UI インターフェイスの応答性が向上します (レンダリング速度が速くなります)。「コード スケジューリング」を通じて、時間を要求する必要があるコードが最初にイベント ループに配置され、後で実行されるため、UI は最初に表示をレンダリングします。
非同期プログラミングの良い使用例は、AJAX リクエストです。リクエストには時間がかかる場合があるため、非同期リクエストを使用すると、クライアントが応答を待っている間に他のコードを実行できます。
しかし、これによって問題が発生します - リクエストはブラウザの WEB API によって処理されますが、他のコードを非同期にするにはどうすればよいでしょうか? たとえば、成功した場合のコードは次のとおりです。コールバックは非常に CPU を集中的に使用します:
var result = performCPUIntensiveCalculation();
performCPUIntensiveCalculation
が HTTP リクエストではなくブロッキング コード (大量のコンテンツを含む for ループなど) の場合、クリアする方法はありません。イベント ループが時間内に発生すると、ブラウザの UI レンダリングがブロックされ、ページは時間内にユーザーに応答できなくなります。
これは、非同期関数はシングルスレッド JavaScript 言語の制限のごく一部しか解決できないことを意味します。
場合によっては、setTimeout
を使用して、長時間実行される計算をブロックできます。setTimeout
を使用して、ページを取得するために計算を一時的に非同期キューに入れることができます。レンダリングが高速化。たとえば、複雑な計算を別々の setTimeout
呼び出しでバッチ処理することで、イベント ループ内の別々の「スポット」に配置でき、UI レンダリング/応答の実行時間を短縮できます。
数値の配列の平均を計算する単純な関数を見てください:
上記のコードを書き換えて非同期性を「シミュレート」する方法は次のとおりです:
function averageAsync(numbers, callback) { var len = numbers.length, sum = 0; if (len === 0) { return 0; } function calculateSumAsync(i) { if (i <p>setTimeout 関数を使用すると、計算の各ステップがイベント ループにさらに追加されます。各計算の間には、他の計算が行われるのに十分な時間があり、ブラウザーがレンダリングできるようになります。 </p><h2>Web Worker はこの問題を解決できます</h2><p>HTML5 は、次のような多くの新機能をもたらします:</p>
Web Worker の役割は、JavaScript 用のマルチスレッド環境を作成することです。これにより、メインスレッドがワーカー スレッドを作成し、後者にいくつかのタスクを割り当てることができるようになります。実行のためです。メイン スレッドの実行中、ワーカー スレッドはバックグラウンドで実行され、この 2 つは相互に干渉しません。ワーカー スレッドが計算タスクを完了するまで待ってから、結果をメイン スレッドに返します。この利点は、一部のコンピューティング集約型または高レイテンシーのタスクがワーカー スレッドの負担となり、メイン スレッド (通常は UI インタラクションを担当) がスムーズになり、ブロックされたり速度が低下したりしないことです。
「JavaScript はシングルスレッド言語ではないのですか?」と疑問に思うかもしれません。
実際、JavaScript はスレッド モデルを定義しない言語です。 Web ワーカーは JavaScript の一部ではありませんが、JavaScript を通じてアクセスできるブラウザ機能です。歴史的に、ほとんどのブラウザはシングルスレッドであり (もちろん、これは変わりました)、ほとんどの JavaScript 実装はブラウザ内で行われていました。 Web ワーカーは Node.JS には実装されていません。 Node.js には、cluster と child_process という同様の概念があり、これらもマルチスレッドですが、Web Workers とは異なります。
仕様には 3 種類の Web ワーカーが記載されていることに注意してください。
D dedicated Worker には、それを作成したページからのみアクセスでき、そのページとのみ通信できます。ブラウザがサポートしているものは次のとおりです:
共享 Workers 在同一源(origin)下面的各种进程都可以访问它,包括:iframes、浏览器中的不同tab页(一个tab页就是一个单独的进程,所以Shared Workers可以用来实现 tab 页之间的交流)、以及其他的共享 Workers。以下是浏览器支持的情况:
Service Worker 功能:
在目前阶段,Service Worker 的主要能力集中在网络代理和离线缓存上。具体的实现上,可以理解为 Service Worker 是一个能在网页关闭时仍然运行的 Web Worker。以下是浏览器支持的情况:
本文主要讨论 专用 Workers,没有特别声明的话,Web Workers、Workers都是指代的专用 Workers。
Web Workers 一般通过脚本为 .js
文件来构建,在页面中还通过了一些异步的 HTTP 请求,这些请求是完全被隐藏了的,你只需要调用 Web Worker API.
Worker 利用类线程间消息传递来实现并行性。它们保证界面的实时性、高性能和响应性呈现给用户。
Web Workers 在浏览器中的一个独立线程中运行。因此,它们执行的代码需要包含在一个单独的文件中。这一点很重要,请记住!
让我们看看基本 Workers 是如何创建的:
var worker = new Worker('task.js');
Worker()
构造函数的参数是一个脚本文件,该文件就是 Worker 线程所要执行的任务。由于 Worker 不能读取本地文件,所以这个脚本必须来自网络。如果下载没有成功(比如404错误),Worker 就会默默地失败。
为了启动创建的 Worker,需要调用 postMessage
方法:
worker.postMessage();
为了在 Web Worker 和创建它的页面之间进行通信,需要使用 postMessage
方法或 Broadcast Channel。
新浏览器支持JSON对象作为方法的第一个参数,而旧浏览器只支持字符串。
来看一个示例,通过将 JSON 对象作为一个更“复杂”的示例传递,创建 Worker 的页面如何与之通信。传递字符串跟传递对象的方式也是一样的。
让我们来看看下面的 HTML 页面(或者更准确地说是它的一部分):
<button>Start computation</button> <script> function startComputation() { worker.postMessage({'cmd': 'average', 'data': [1, 2, 3, 4]}); } var worker = new Worker('doWork.js'); worker.addEventListener('message', function(e) { console.log(e.data); }, false); </script>
然后这是 worker 中的 js 代码:
self.addEventListener('message', function(e) { var data = e.data; switch (data.cmd) { case 'average': var result = calculateAverage(data); // 从数值数组中计算平均值的函数 self.postMessage(result); break; default: self.postMessage('Unknown command'); } }, false);
当单击该按钮时,将从主页调用 postMessage
。postMessage 行将 JSON 对象传给Worker。Worker 通过定义的消息处理程序监听并处理该消息。
当消息到达时,实际的计算在worker中执行,而不会阻塞事件循环。Worker 检查传递的事件参数 e
,像执行 JavaScript 函数一样,处理完成后,把结果传回给主页。
在 Worker 作用域中,this 和 self 都指向 Worker 的全局作用域。
有两种方法可以停止 Worker:从主页调用worker.terminate()
或在worker
内部调用self.close()
。
Broadcast Channel API 允许同一原始域和用户代理下的所有窗口,iFrames 等进行交互。也就是说,如果用户打开了同一个网站的的两个标签窗口,如果网站内容发生了变化,那么两个窗口会同时得到更新通知。
还是不明白?就拿 Facebook 作为例子吧,假如你现在已经打开 了Facebook 的一个窗口,但是你此时还没有登录,此时你又打开另外一个窗口进行登录,那么你就可以通知其他窗口/标签页去告诉它们一个用户已经登录了并请求它们进行相应的页面更新。
// Connection to a broadcast channel var bc = new BroadcastChannel('test_channel'); // Example of sending of a simple message bc.postMessage('This is a test message.'); // Example of a simple event handler that only // logs the message to the console bc.onmessage = function (e) { console.log(e.data); } // Disconnect the channel bc.close()
可以从下面这张图,在视觉上来清晰地感受 Broadcast Channel:
Broadcast Channel 浏览器支持比较有限:
有两种方式发送消息给Web Workers:
JavaScript のマルチスレッドの性質により、Web Workers は JavaScript 機能のサブセットにしかアクセスできません。その機能の一部を次に示します。
Web ワーカーは、マルチスレッドの性質のため、JavaScript 機能のサブセットにのみアクセスできます。使用可能なプロパティのリストは次のとおりです。
importScripts()
外部スクリプトのインポート残念ながら、Web Workers はいくつかの非常に重要な JavaScript 機能にアクセスできません:
これは、Web Worker が DOM (したがって UI ) を操作できないことを意味します。これは難しい場合もありますが、Web ワーカーの正しい使用方法を理解すると、Web ワーカーを別個の「コンピューター」として使用し始め、すべての UI 変更がページ コード内で行われるようになります。作業者は面倒な作業をすべて実行し、完了すると結果をページに返します。
JavaScript コードと同様に、Web ワーカーによってスローされたエラーも処理する必要があります。 Worker の実行中にエラーが発生した場合、ErrorEvent
イベントがトリガーされます。このインターフェイスには、問題のトラブルシューティングに役立つ 3 つの便利なプロパティが含まれています。
例は次のとおりです。
Inここでは、ワーカーを作成し、エラー イベントのリッスンを開始したことがわかります。
ワーカー内 (workerWithError.js
) では、 unknown#xxx に 2 を乗算して例外を作成します。例外は最初のスクリプトに伝播され、その後ページを通じてエラー イベントが監視され、エラーが捕捉されます。
スペル チェック: 基本的なスペル チェック プログラムのワークフローは次のとおりです。プログラムは、正しく綴られた単語のリストが含まれる辞書ファイルを読み取ります。実際のテキスト検索をより効率的に行うために、辞書は検索ツリーに解析されます。単語がチェッカーに提供されると、プログラムはその単語が事前に構築された検索ツリーに存在するかどうかをチェックします。単語がツリー内に見つからない場合は、置換文字を置き換えて、それがユーザーが書きたい単語であるかどうかをテストし、それが有効な単語であるかどうかをテストすることで、ユーザーに代替スペルを提供できます。これらの処理はすべて Web Worker 上で行うことができ、ユーザーはブロックされることなく単語や文章を入力することができ、Web Worker がバックグラウンドで単語が正しいかどうかをチェックし、代替単語を提供します。
# プログラミングについてさらに詳しく知りたい場合は、php トレーニング# に注目してください。 ## カラム!
以上がJavaScript Web Workers の構成要素と 5 つの使用シナリオの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。