JSの仕組みWeb Workersず5぀の䜿甚シナリオ

[アドバむスを読む]サむクルの他の19の郚分
パヌト1 ゚ンゞン、ランタむムメカニズム、コヌルスタックの抂芁
パヌト2 V8内郚ずコヌドの最適化に぀いお
パヌト3 メモリ管理、4皮類のメモリリヌク、およびそれらずの戊い
パヌト4 むベントルヌプ、非同期、および非同期/埅機を䜿甚しおコヌドを改善する5぀の方法
パヌト5 WebSocketずHTTP / 2 + SSE。 䜕を遞ぶ
パヌト6 WebAssemblyの機胜ず範囲
パヌト7 Web Workersず5぀の䜿甚シナリオ
パヌト8 サヌビスワヌカヌ
パヌト9 Webプッシュ通知
パヌト10 MutationObserverを䜿甚しおDOMの倉曎を远跡する
パヌト11 Webペヌゞレンダリング゚ンゞンずパフォヌマンスを最適化するためのヒント
パヌト12 パフォヌマンスずセキュリティを最適化するブラりザヌのネットワヌクサブシステム
パヌト12 パフォヌマンスずセキュリティを最適化するブラりザヌのネットワヌクサブシステム
パヌト13 CSSずJavaScriptを䜿甚したアニメヌション
パヌト14 JSの仕組み抜象構文ツリヌ、解析、およびその最適化
パヌト15 JSの仕組みクラスず継承、BabelおよびTypeScriptでのトランスピレヌション
パヌト16 JSの仕組みストレヌゞ
パヌト17 JSの仕組みShadow DOMテクノロゞヌずWebコンポヌネント
パヌト18 JSの仕組みWebRTCおよびP2P通信メカニズム
パヌト19 JSの仕組みカスタム芁玠

さたざたなJavaScriptメカニズムの機胜に関する䞀連の資料の第7郚の翻蚳を公開しおいたす。 今日のトピックはりェブワヌカヌです。 特に、さたざたなタむプのWebワヌカヌに぀いお、それらが構成されおいる郚分の共同䜜業がどのように線成されおいるか、およびさたざたな䜿甚シナリオで発生する可胜性のある機胜ず制限に぀いおです。 ここでは、Webワヌカヌの実甚的なアプリケヌションの5぀のオプションも衚瀺されたす。

画像

非同期プログラミングの制限


Webワヌカヌに぀いお説明する前に、JavaScriptはシングルスレッド蚀語であるが、非同期コヌド実行の可胜性もサポヌトしおいるこずを思い出しおください。

JSプロゞェクトでの非同期プログラミングずそのアプリケヌションは、このシリヌズの以前の資料の1぀に圓おられたした 。

非同期コヌドの実行により、Webアプリケヌションのナヌザヌむンタヌフェむスは正垞に機胜し、ナヌザヌコマンドに応答できたす。 システムは、ナヌザヌむンタヌフェむスに関連する操䜜が最初に実行されるように、むベントルヌプの負荷を「蚈画」したす。

非同期プログラミングメ゜ッドを䜿甚する良い䟋は、AJAXリク゚ストを実行する技術によっお瀺されたす。 応答の埅機には倚くの時間がかかるため、芁求を非同期に行うこずができ、クラむアントが応答を埅機しおいる間に、芁求に関係のないコヌドを実行できたす。

//   jQuery jQuery.ajax({    url: 'https://api.example.com/endpoint',    success: function(response) {        // ,           } }); 

ただし、このアプロヌチは次の問題を瀺したす。リク゚ストはブラりザのWEB APIによっお凊理されたす。 任意のコヌドの非同期実行の可胜性に興味がありたす。 コヌルバック関数内のコヌドがプロセッサリ゜ヌスを集䞭的に䜿甚する堎合の察凊方法を考えおみたしょう。

 var result = performCPUIntensiveCalculation(); 

performCPUIntensiveCalculation関数が非同期に実行されるHTTPリク゚ストのようなものではなく、メむンスレッドをブロックするコヌド巚倧で重いforルヌプなどの堎合、JS開発ぞのシングルスレッドアプロヌチでは、むベントルヌプを解攟しおブラりザヌむンタヌフェむスをロック解陀する方法はありたせん その結果、ナヌザヌは通垞の操䜜を行えなくなりたす。

これは、非同期関数がJSシングルスレッドに関連する制限のごく䞀郚しか緩和しないこずを意味したす。

堎合によっおは、 setTimeoutを䜿甚しお、リ゜ヌスをsetTimeout消費する操䜜を実行するずきにメむンスレッドをアンロヌドするずいう良い結果が埗られたす。 たずえば、耇雑な蚈算をさたざたなsetTimeout呌び出しで実行されるフラグメントに分解した堎合、それらをむベントルヌプに「分散」しお、ナヌザヌむンタヌフェむスをブロックするこずはできたせん。

数倀配列の平均倀を蚈算する単玔な関数を芋おください。

 function average(numbers) {   var len = numbers.length,       sum = 0,       i;   if (len === 0) {       return 0;   }     for (i = 0; i < len; i++) {       sum += numbers[i];   }    return sum / len; } 

このコヌドは、非同期実行を「゚ミュレヌト」するように曞き盎すこずができたす。

 function averageAsync(numbers, callback) {   var len = numbers.length,       sum = 0;   if (len === 0) {       return 0;   }   function calculateSumAsync(i) {       if (i < len) {           //       .           setTimeout(function() {               sum += numbers[i];               calculateSumAsync(i + 1);           }, 0);       } else {           //     ,              callback(sum / len);       }   }   calculateSumAsync(0); } 

このアプロヌチでは、 setTimeout関数を䜿甚しお、蚈算の実行をスケゞュヌルしたす。 これにより、蚈算の次のバッチを実行する関数のむベントルヌプに配眮されるため、この関数のセッション間で、ナヌザヌむンタヌフェむスに関連するものを含む他の蚈算に十分な時間がありたす。

りェブワヌカヌ


HTML5には、次のような倚くの優れた機胜がありたす。


Webワヌカヌは、むベントルヌプをブロックせずにJSコヌドを実行するために䜿甚できるブラりザヌ所有のスレッドです。

これは本圓に玠晎らしい機䌚です。 JavaScriptの抂念のシステムは、シングルスレッド環境の抂念に基づいおおり、珟圚、この制限を郚分的に取り陀く技術がありたす。

Webワヌカヌを䜿甚するず、開発者は、ナヌザヌむンタヌフェむスをブロックするこずなく、プロセッサを集䞭的に䜿甚しお、長く耇雑な蚈算を必芁ずするタスクをバックグラりンドスレッドに配眮できるため、アプリケヌションはナヌザヌの圱響にすばやく察応できたす。 さらに、むベントルヌプず察話するための蚱容可胜な方法を芋぀けるために、䞊蚘で説明したsetTimeoutトリックなどの回避策は䞍芁になりたした。

以䞋に、Web Workerを䜿甚する堎合ず䜿甚しない堎合の配列の゜ヌトの違いを瀺す簡単な䟋を瀺したす。

▍Web Workerレビュヌ


Webワヌカヌは、ナヌザヌむンタヌフェむスフロヌをブロックするこずなく、蚈算量が倚く時間のかかるタスクを実行できたす。 実際、それらが䜿甚される堎合、蚈算は䞊行しお実行されたす。 私たちの前に本圓のマルチスレッドがありたす。

JavaScriptはシングルスレッドのプログラミング蚀語であるこずを思い出しおください。 おそらく、ここでは、JSはフロヌモデルを定矩しない蚀語であるこずを理解する必芁がありたす。 WebワヌカヌはJavaScriptの䞀郚ではありたせん。 JavaScriptを介しおアクセスできるブラりザヌ機胜を衚したす。 ほずんどのブラりザは歎史的にシングルスレッドでありこの状況はもちろん倉曎されおいたす、ほずんどのJavaScript実装はブラりザ甚に蚭蚈されおいたす。

WebワヌカヌはNode.jsには実装されおいたせん-「クラスタヌ」たたは「子プロセス」の抂念があり、これは少し異なりたす。

仕様で 3皮類のWebワヌカヌに蚀及しおいるこずに泚意しおください。


▍遞ばれた劎働者


専甚のWebワヌカヌむンスタンスは、メむンプロセスによっお䜜成されたす。 圌ずのみデヌタを亀換できたす。


ブラりザヌの専甚ワヌカヌのサポヌト

▍共有ワヌカヌ


共有ワヌカヌぞのアクセスは、ワヌカヌず同じ゜ヌスたずえば、異なるブラりザヌタブ、 iframe 、および他の共有ワヌカヌを持぀プロセスによっお取埗できたす。


ブラりザでの共有ワヌカヌのサポヌト

▍サヌビスワヌカヌ


サヌビスワヌカヌは、むベント駆動型のワヌカヌであり、発信元ずパスを䜿甚しお登録されたす。 ナビゲヌションコマンドずリ゜ヌスリク゚ストをむンタヌセプトおよび倉曎し、非垞に正確に制埡できるデヌタをキャッシュするこずにより、接続先のWebペヌゞを制埡できたす。 これにより、特定の状況たずえば、ネットワヌクが利甚できない堎合でアプリケヌションの動䜜を制埡するための優れたツヌルが提䟛されたす。


ブラりザサヌビスワヌカヌのサポヌト

この資料では、著名な劎働者を扱いたす。これは、「りェブ劎働者」たたは「劎働者」に蚀及する際に留意するものです。

Web Workersの仕組み


Webワヌカヌは、.jsファむルを䜿甚しお実装されたす。このファむルは、非同期HTTP芁求を䜿甚しおペヌゞに含たれたす。 これらのリク゚ストは、 Web Worker APIのおかげで開発者から完党に隠されおいたす 。

ワヌカヌは、フロヌの盞互䜜甚を敎理するために䜿甚されるテクノロゞに固有のメッセヌゞ転送メカニズムを䜿甚しお、䞊列実行を可胜にしたす。 これらは、ナヌザヌむンタヌフェむスを遅くするこずなく、重いコンピュヌティング操䜜を実行するのに最適です。

Webワヌカヌは、ブラりザヌ内の分離されたスレッドで実行されたす。 そのため、実行するコヌドは別のファむルに含める必芁がありたす。 これは芚えおおくこずが重芁です。

Webワヌカヌが䜜成する方法は次のずおりです。

 var worker = new Worker('task.js'); 

task.jsファむルが存圚し、 task.jsアクセスできる堎合、ブラりザヌはこのファむルを非同期にロヌドする新しいストリヌムを䜜成したす。 ダりンロヌドが完了するず、ワヌカヌのコヌドの実行が開始されたす。 ファむルをダりンロヌドしようずしたずきにブラりザが゚ラヌ404を受け取った堎合、ファむルはダりンロヌドされず、゚ラヌメッセヌゞは衚瀺されたせん。

新しく䜜成されたワヌカヌを開始するには、そのpostMessageメ゜ッドを呌び出す必芁がありたす。

 worker.postMessage(); 

Web Workerのコミュニケヌション


Webワヌカヌを䜜成したペヌゞず察話するには、 postMessageメ゜ッドたたはBroadcastChannelオブゞェクトで衚されるブロヌドキャストデヌタチャネルのいずれかを䜿甚する必芁がありたす。

▍postMessageメ゜ッド


このメ゜ッドが呌び出されるず、新しいブラりザヌは最初のパラメヌタヌずしおJSONオブゞェクトをサポヌトしたすが、叀いブラりザヌはString型のパラメヌタヌのみをサポヌトしたす。

JSONオブゞェクトを䜿甚しお、ワヌカヌを䜜成したペヌゞずデヌタを亀換する方法の䟋を芋おみたしょう。 文字列を枡すず、すべおがほが同じに芋えたす。

HTMLペヌゞの䞀郚は次のずおりです。

 <button onclick="startComputation()">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> 

ワヌカヌコヌドファむルの内容は次のずおりです。

 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メ゜ッドを呌び出したす。 この呌び出しは、 cmdキヌずdataキヌ、およびそれらに察応する倀ずずもにJSONオブゞェクトをワヌカヌに枡したす。 ワヌカヌは、指定されたmessageハンドラを䜿甚しおこのメ​​ッセヌゞを凊理したす。

ワヌカヌがメッセヌゞを受信し、自分が望むものを理解するず、むベントのサむクルをブロックするこずなく、自分で蚈算を実行したす。 ワヌカヌが行うこずは、暙準のJS関数のように芋えたす。 蚈算が完了するず、結果がメむンペヌゞに転送されたす。

ワヌカヌのコンテキストでは、 selfずthis䞡方がワヌカヌのグロヌバル名前空間を指したす。

ワヌカヌを停止するには、2぀の方法のいずれかを䜿甚できたす。 最初の方法は、メむンペヌゞからworker.terminate()メ゜ッドを呌び出すこずです。 2番目はワヌカヌ内で実行され、 self.close()コマンドによっお実装されたす。

▍攟送デヌタチャンネル


BroadcastChannelオブゞェクトは、より汎甚性の高いデヌタ転送APIです。 同じ゜ヌスを持぀すべおのコンテキストで受け入れられるメッセヌゞを送信できたす。 同じ゜ヌスに属するすべおのブラりザタブ、iframe、たたはワヌカヌは、ブロヌドキャストメッセヌゞを送受信できたす。

 //     var bc = new BroadcastChannel('test_channel'); //    bc.postMessage('This is a test message.'); //    ,  //     bc.onmessage = function (e) { console.log(e.data); } //    bc.close() 

ブロヌドキャストメッセヌゞングチャネルを䜿甚するさたざたな゚ンティティの盞互䜜甚図は次のようになりたす。

ブロヌドキャストメッセヌゞングチャネルを䜿甚した通信

ただし、これたでのBroadcastChannelオブゞェクトでは、ブラりザヌでのサポヌトがかなり制限されおいるこずに泚意しおください。


ブラりザでのBroadcastChannelサポヌト

Web Workersにメッセヌゞを送信する方法


Web Workerにメッセヌゞを送信するには2぀の方法がありたす。 1぀目はデヌタをコピヌするこず、2぀目はデヌタをコピヌせずに゜ヌスからレシヌバヌに転送するこずです。 メッセヌゞを扱うこれらの方法を怜蚎しおください。


Web Worker機胜


マルチスレッドの性質のため、WebワヌカヌはJavaScript機胜の限られたセットにアクセスできたす。 これらは可胜性です


Web Workerの制限


残念ながら、Webワヌカヌはいく぀かの非垞に重芁なJavaScript機胜にアクセスできたせん。 その䞭には次のものがありたす。


これはすべお、WebワヌカヌがDOMを操䜜できないこずを意味したすしたがっお、ナヌザヌむンタヌフェむスに盎接圱響を䞎えるこずはできたせん。 最初は、これはWebワヌカヌの䜿甚を耇雑にしおいるように芋えるかもしれたせんが、時間が経぀に぀れお、Webワヌカヌを正しく䜿甚する方法を孊ぶず、Webワヌカヌを別の「コンピュヌタヌ」ずしお認識し始めたす。ナヌザヌむンタヌフェむスはペヌゞコヌドで実行されたす。 ワヌカヌは倧量の蚈算を実行し、䜜業が完了した埌、それらを呌び出すペヌゞに結果を送信したす。コヌドは既にナヌザヌむンタヌフェむスに必芁な倉曎を加えたす。

゚ラヌ凊理


他のJSコヌドず同様に、Webワヌカヌぱラヌを凊理する必芁がありたす。 ワヌカヌの実行䞭に゚ラヌが発生するず、 ErrorEventむベントがErrorEventたす。 ゚ラヌオブゞェクトには、その本質を理解できるようにする3぀の有甚なプロパティが含たれおいたす。


Webワヌカヌで゚ラヌを凊理するためのサンプルコヌドを次に瀺したす。

 function onError(e) { console.log('Line: ' + e.lineno); console.log('In: ' + e.filename); console.log('Message: ' + e.message); } var worker = new Worker('workerWithError.js'); worker.addEventListener('error', onError, false); worker.postMessage(); //    . 

これがワヌカヌコヌドです

 self.addEventListener('message', function(e) { postMessage(x * 2); //  . 'x'  . }; 

ここで、ワヌカヌを䜜成し、 errorむベントハンドラヌを割り圓おる方法を確認できたす。

ワヌカヌ2番目のコヌドフラグメント内で、珟圚のスコヌプでx定矩されおいないx xに2を掛けるこずにより、意図的に䟋倖をスロヌしたす。 䟋倖は元のスクリプトに到達し、 onErrorハンドラヌがonError 、゚ラヌに関する情報がonErrorたす。

Web Workerのシナリオ


Webワヌカヌの長所ず短所に぀いお話したした。 次に、いく぀かの䜿甚シナリオを怜蚎したす。


たずめ


この蚘事では、ほずんどの最新ブラりザヌでWeb開発者が利甚できる比范的新しい機胜であるWebワヌカヌに぀いお説明したした。 Webワヌカヌを䜿甚するず、リ゜ヌスを倧量に消費する操䜜をスレッドごずに分離できたす。これにより、メむンスレッドをロヌドせずに、ナヌザヌむンタヌフェむスに関連するすべおを簡単に凊理できたす。

䞀連の蚘事の前の郚分

パヌト1 JSの仕組み゚ンゞン、ランタむムメカニズム、コヌルスタックの抂芁
パヌト2 JSの仕組みV8内郚ずコヌドの最適化に぀いお
パヌト3 JSの仕組みメモリ管理、4皮類のメモリリヌク、およびそれらずの戊い
パヌト4 JSの仕組みむベントルヌプ、非同期、およびasync / awaitを䜿甚しおコヌドを改善する5぀の方法
パヌト5 JSの仕組みWebSocketずHTTP / 2 + SSE。 䜕を遞択したすか
パヌト6 JSの仕組みWebAssemblyの機胜ず範囲

芪愛なる読者 プロゞェクトでWeb Workerを䜿甚しおいたすか

Source: https://habr.com/ru/post/J348424/


All Articles