Webワーカーを使用したReactアプリでの長時間実行タスクの管理

公開: 2022-03-10
簡単なまとめ↬このチュートリアルでは、WebワーカーAPIを使用して、Webワーカーを活用するサンプルWebアプリを構築することにより、JavaScriptアプリで時間のかかるUIブロックタスクを管理する方法を学習します。 最後に、すべてをReactアプリケーションに転送して記事を終了します。

Webアプリケーションに関しては、応答時間は非常に重要です。 ユーザーは、アプリが何をしているかに関係なく、瞬時の応答を要求します。 人の名前だけを表示する場合でも、数字を計算する場合でも、Webアプリのユーザーは、アプリが毎回コマンドに応答することを要求します。 JavaScriptのシングルスレッドの性質を考えると、それを達成するのが難しい場合があります。 ただし、この記事では、Web WorkerAPIを活用してより良いエクスペリエンスを提供する方法を学習します。

この記事を書く際に、私は次の仮定をしました:

  1. フォローできるようにするには、JavaScriptとドキュメントAPIに少なくともある程度精通している必要があります。
  2. また、Create React Appを使用して新しいReactプロジェクトを正常に開始できるように、Reactの実用的な知識が必要です。

このトピックについてさらに洞察が必要な場合は、「その他のリソース」セクションにいくつかのリンクを含めて、理解を深めることができます。

まず、Webワーカーを使い始めましょう。

Webワーカーとは何ですか?

Web Workerとその解決対象の問題を理解するには、JavaScriptコードが実行時にどのように実行されるかを把握する必要があります。 実行時に、JavaScriptコードは順番に順番に実行されます。 コードの一部が終了すると、次のコードが実行を開始します。 技術用語では、JavaScriptはシングルスレッドであると言います。 この動作は、コードの一部が実行を開始すると、後続のすべてのコードがそのコードの実行が終了するまで待機する必要があることを意味します。 したがって、コードのすべての行は、その後に続く他のすべての実行を「ブロック」します。 したがって、すべてのコードができるだけ早く終了することが望ましいです。 コードの一部が完了するまでに時間がかかりすぎると、プログラムが機能しなくなったように見えます。 ブラウザでは、これはフリーズした応答のないページとして表示されます。 極端な場合には、タブが完全にフリーズします。

シングルレーンでの運転を想像してみてください。 前方のドライバーのいずれかが何らかの理由で移動を停止した場合は、渋滞が発生しています。 Javaのようなプログラムを使用すると、トラフィックは他のレーンで継続する可能性があります。 したがって、Javaはマルチスレッドであると言われています。 Webワーカーは、マルチスレッドの動作をJavaScriptにもたらす試みです。

以下のスクリーンショットは、Web Worker APIが多くのブラウザーでサポートされていることを示しているため、自信を持って使用できるはずです。

Webワーカーのブラウザサポートチャートを表示する
WebWorkersブラウザのサポート。 (大プレビュー)

Webワーカーは、UIに干渉することなくバックグラウンドスレッドで実行され、イベントハンドラーを介してWebワーカーを作成したコードと通信します。

Webワーカーの優れた定義は、MDNに由来します。

「ワーカーは、コンストラクター(名前付きJavaScriptファイルを実行するWorker()を使用して作成されたオブジェクトです。このファイルには、ワーカースレッドで実行されるコードが含まれています。ワーカーは、現在のwindowとは異なる別のグローバルコンテキストで実行されます。 、 windowショートカットを使用して、現在のグローバルスコープを取得します( Worker内のselfの代わりに、エラーが返されます。」

ワーカーは、 Workerコンストラクターを使用して作成されます。

 const worker = new Worker('worker-file.js')

いくつかの例外を除いて、ほとんどのコードをWebワーカー内で実行することが可能です。 たとえば、ワーカー内からDOMを操作することはできません。 document APIへのアクセスはありません。

ワーカーとワーカーを生成するスレッドは、 postMessage()メソッドを使用して相互にメッセージを送信します。 同様に、 onmessageイベントハンドラーを使用してメッセージに応答します。 この違いを理解することが重要です。 メッセージの送信は、メソッドを使用して実行されます。 メッセージを受信するには、イベントハンドラーが必要です。 受信中のメッセージは、イベントのdata属性に含まれています。 この例は次のセクションで説明します。 しかし、私たちが話し合っている種類の労働者は「献身的な労働者」と呼ばれていることを簡単に述べさせてください。 これは、ワーカーがそれを呼び出したスクリプトにのみアクセスできることを意味します。 複数のスクリプトからアクセスできるワーカーを作成することもできます。 これらは共有ワーカーと呼ばれ、以下に示すように、 SharedWorkerコンストラクターを使用して作成されます。

 const sWorker = new SharedWorker('shared-worker-file.js')

ワーカーの詳細については、このMDNの記事を参照してください。 この記事の目的は、Webワーカーの使用を開始することです。 n番目のフィボナッチ数を計算して取得しましょう。

ジャンプした後もっと! 以下を読み続けてください↓

N番目のフィボナッチ数の計算

注:このセクションと次の2つのセクションでは、VSCode上のLiveServerを使用してアプリを実行しています。 あなたは確かに何か他のものを使うことができます。

これはあなたが待ち望んでいたセクションです。 最後に、Webワーカーの動作を確認するためのコードを記述します。 まあ、それほど速くはありません。 Webワーカーが解決するような問題に遭遇しない限り、Webワーカーの仕事に感謝することはできません。 このセクションでは、問題の例を示し、次のセクションでは、Webワーカーがどのように改善に役立つかを示します。

ユーザーがn番目のフィボナッチ数を計算できるWebアプリを構築していると想像してください。 「フィボナッチ数」という用語を初めて使用する場合は、ここで詳細を読むことができますが、要約すると、フィボナッチ数は、各数が先行する2つの数の合計になるような一連の数です。

数学的には、次のように表されます。

したがって、シーケンスの最初の数個は次のとおりです。

1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89 ...

一部のソースでは、シーケンスはF 0 = 0で始まります。この場合、次の式はn > 1に対して成り立ちます。

この記事では、F 1 = 1から始めます。数式からすぐにわかることの1つは、数値が再帰的なパターンに従うことです。 現在のタスクは、n番目のフィボナッチ数(FN)を計算する再帰関数を作成することです。

何度か試してみると、以下の機能を簡単に思いつくことができると思います。

 const fib = n => { if (n < 2) { return n // or 1 } else { return fib(n - 1) + fib(n - 2) } }

機能はシンプルです。 nが2未満の場合は、n(または1)を返します。それ以外の場合は、 n-1およびn-2 2FNの合計を返します。 矢印関数と三項演算子を使用すると、ワンライナーを思い付くことができます。

 const fib = n => (n < 2 ? n : fib(n-1) + fib(n-2))

この関数の時間計算量は0(2 n )です。 これは単に、nの値が増加すると、合計の計算に必要な時間が指数関数的に増加することを意味します。 これにより、nの値が大きい場合、UIに干渉する可能性のある非常に長時間実行されるタスクが発生します。 これを実際に見てみましょう。

これは、この特定の問題を解決するための最良の方法ではありません。 この方法を使用するという私の選択は、この記事の目的のためです。

まず、新しいフォルダを作成し、好きな名前を付けます。 次に、そのフォルダー内にsrc/フォルダーを作成します。 また、ルートフォルダにindex.htmlファイルを作成します。 src/フォルダー内に、 index.jsという名前のファイルを作成します。

index.htmlを開き、次のHTMLコードを追加します。

 <!DOCTYPE html> <html> <head> <link rel="stylesheet" href="styles.css"> </head> <body> <div class="heading-container"> <h1>Computing the nth Fibonnaci number</h1> </div> <div class="body-container"> <p id='error' class="error"></p> <div class="input-div"> <input id='number-input' class="number-input" type='number' placeholder="Enter a number" /> <button id='submit-btn' class="btn-submit">Calculate</button> </div> <div id='results-container' class="results"></div> </div> <script src="/src/index.js"></script> </body> </html>

この部分は非常に単純です。 まず、見出しがあります。 次に、入力とボタンを備えたコンテナがあります。 ユーザーは数値を入力し、「計算」をクリックします。 計算結果を保持するためのコンテナもあります。 最後に、 src/index.jsファイルをscriptタグに含めます。

スタイルシートのリンクを削除できます。 ただし、時間が足りない場合は、使用できるCSSをいくつか定義しました。 ルートフォルダにstyles.cssファイルを作成し、以下にスタイルを追加するだけです。

 body { margin: 0; padding: 0; box-sizing: border-box; } .body-container, .heading-container { padding: 0 20px; } .heading-container { padding: 20px; color: white; background: #7a84dd; } .heading-container > h1 { margin: 0; } .body-container { width: 50% } .input-div { margin-top: 15px; margin-bottom: 15px; display: flex; align-items: center; } .results { width: 50vw; } .results>p { font-size: 24px; } .result-div { padding: 5px 10px; border-radius: 5px; margin: 10px 0; background-color: #e09bb7; } .result-div p { margin: 5px; } span.bold { font-weight: bold; } input { font-size: 25px; } p.error { color: red; } .number-input { padding: 7.5px 10px; } .btn-submit { padding: 10px; border-radius: 5px; border: none; background: #07f; font-size: 24px; color: white; cursor: pointer; margin: 0 10px; }

src/index.jsを開いて、ゆっくりと開発していきましょう。 以下のコードを追加します。

 const fib = (n) => (n < 2 ? n : fib(n - 1) + fib(n - 2)); const ordinal_suffix = (num) => { // 1st, 2nd, 3rd, 4th, etc. const j = num % 10; const k = num % 100; switch (true) { case j === 1 && k !== 11: return num + "st"; case j === 2 && k !== 12: return num + "nd"; case j === 3 && k !== 13: return num + "rd"; default: return num + "th"; } }; const textCont = (n, fibNum, time) => { const nth = ordinal_suffix(n); return ` <p id='timer'>Time: <span class='bold'>${time} ms</span></p> <p><span class="bold" id='nth'>${nth}</span> fibonnaci number: <span class="bold" id='sum'>${fibNum}</span></p> `; };

ここに3つの機能があります。 1つ目は、n番目のFNを計算するために前に見た関数です。 2番目の関数は、整数に適切な接尾辞を付けるための単なる効用関数です。 3番目の関数はいくつかの引数を取り、後でDOMに挿入するマークアップを出力します。 最初の引数は、FNが計算されている番号です。 2番目の引数は計算されたFNです。 最後の引数は、計算の実行にかかる時間です。

まだsrc/index.jsで、前のコードのすぐ下に以下のコードを追加します。

 const errPar = document.getElementById("error"); const btn = document.getElementById("submit-btn"); const input = document.getElementById("number-input"); const resultsContainer = document.getElementById("results-container"); btn.addEventListener("click", (e) => { errPar.textContent = ''; const num = window.Number(input.value); if (num < 2) { errPar.textContent = "Please enter a number greater than 2"; return; } const startTime = new Date().getTime(); const sum = fib(num); const time = new Date().getTime() - startTime; const resultDiv = document.createElement("div"); resultDiv.innerHTML = textCont(num, sum, time); resultDiv.className = "result-div"; resultsContainer.appendChild(resultDiv); });

まず、 document APIを使用して、HTMLファイル内のDOMノードを取得します。 エラーメッセージを表示する段落への参照を取得します。 入力; 計算ボタンと結果を表示するコンテナ。

次に、「クリック」イベントハンドラーをボタンにアタッチします。 ボタンがクリックされると、input要素内にあるものをすべて取得して数値に変換し、2未満のものを取得すると、エラーメッセージを表示して戻ります。 2より大きい数を取得した場合は、続行します。 まず、現在の時刻を記録します。 その後、FNを計算します。 それが終了すると、計算にかかった時間を表す時間差が得られます。 コードの残りの部分では、新しいdivを作成します。 次に、その内部HTMLを、前に定義したtextCont()関数の出力になるように設定します。 最後に、(スタイリングのために)クラスを追加し、結果コンテナに追加します。 これの効果は、各計算が前の計算の下の別々のdivに表示されることです。

43までの計算されたフィボナッチ数を表示
いくつかのフィボナッチ数。 (大プレビュー)

数が増えると、計算時間も(指数関数的に)増加することがわかります。 たとえば、30から35に、計算時間が13msから130msにジャンプしました。 それでも、これらの操作は「高速」であると見なすことができます。 40では、1秒を超える計算時間が表示されます。 私のマシンでは、ここからページが応答しなくなることに気づき始めます。 この時点で、計算が進行している間はページを操作できなくなります。 入力に集中したり、他のことをしたりすることはできません。

JavaScriptがシングルスレッドであることについて話したときのことを思い出してください。 ええと、そのスレッドはこの長時間実行される計算によって「ブロック」されているので、他のすべてはそれが終了するのを「待つ」必要があります。 それはあなたのマシン上でより低いまたはより高い値で始まるかもしれません、しかしあなたはそのポイントに到達するにちがいありません。 44の計算には10秒近くかかったことに注意してください。Webアプリで他にやることがあった場合、ユーザーは続行する前にFib(44)が終了するのを待つ必要があります。 ただし、その計算を処理するためにWebワーカーをデプロイした場合、ユーザーはそれが実行されている間、他の何かを続行できます。

ここで、Webワーカーがこの問題の克服にどのように役立つかを見てみましょう。

動作中のWebワーカーの例

このセクションでは、n番目のFNを計算するジョブをWebワーカーに委任します。 これにより、メインスレッドが解放され、計算の進行中にUIの応答性が維持されます。

Webワーカーの使用を開始するのは驚くほど簡単です。 方法を見てみましょう。 新しいファイルsrc/fib-worker.js作成します。 次のコードを入力します。

 const fib = (n) => (n < 2 ? n : fib(n - 1) + fib(n - 2)); onmessage = (e) => { const { num } = e.data; const startTime = new Date().getTime(); const fibNum = fib(num); postMessage({ fibNum, time: new Date().getTime() - startTime, }); };

このファイル内でn番目のフィボナッチ数fibを計算する関数を移動したことに注意してください。 このファイルは、Webワーカーによって実行されます。

「Webワーカーとは」のセクションで、 Webワーカーとその親がonmessageイベントハンドラーとpostMessage()メソッドを使用して通信することを思い出してください。 ここでは、 onmessageイベントハンドラーを使用して、親スクリプトからのメッセージをリッスンしています。 メッセージを受け取ったら、イベントのデータ属性から番号を分解します。 次に、現在の時刻を取得して計算を開始します。 結果の準備ができたら、 postMessage()メソッドを使用して、結果を親スクリプトにポストバックします。

src/index.jsを開いて変更を加えましょう。

 ... const worker = new window.Worker("src/fib-worker.js"); btn.addEventListener("click", (e) => { errPar.textContent = ""; const num = window.Number(input.value); if (num < 2) { errPar.textContent = "Please enter a number greater than 2"; return; } worker.postMessage({ num }); worker.onerror = (err) => err; worker.onmessage = (e) => { const { time, fibNum } = e.data; const resultDiv = document.createElement("div"); resultDiv.innerHTML = textCont(num, fibNum, time); resultDiv.className = "result-div"; resultsContainer.appendChild(resultDiv); }; });

最初に行うことは、 Workerコンストラクターを使用してWebワーカーを作成することです。 次に、ボタンのイベントリスナー内で、 worker.postMessage({ num })を使用してワーカーに番号を送信します。 その後、ワーカーのエラーをリッスンする関数を設定します。 ここでは、単にエラーを返します。 DOMで表示するなど、必要に応じてさらに多くのことを実行できます。 次に、ワーカーからのメッセージをリッスンします。 メッセージを受け取ったら、 timefibNumを分解し、それらをDOMに表示するプロセスを続行します。

Webワーカー内では、 onmessageイベントはワーカーのスコープで使用できるため、 self.onmessageおよびself.postMessage()として記述できることに注意してください。 ただし、親スクリプトでは、これらをワーカー自体にアタッチする必要があります。

以下のスクリーンショットでは、Chrome DevToolsの[ソース]タブにWebワーカーファイルが表示されます。 注意すべき点は、入力した番号に関係なく、UIの応答性が維持されることです。 この振る舞いはWebワーカーの魔法です。

アクティブなWebワーカーファイルの表示
実行中のWebワーカーファイル。 (大プレビュー)

私たちはウェブアプリで多くの進歩を遂げました。 しかし、それを改善するために私たちにできることが他にあります。 現在の実装では、単一のワーカーを使用してすべての計算を処理しています。 実行中に新しいメッセージが届くと、古いメッセージが置き換えられます。 これを回避するために、呼び出しごとに新しいワーカーを作成してFNを計算できます。 次のセクションでそれを行う方法を見てみましょう。

複数のWebワーカーとの連携

現在、すべてのリクエストを1人のワーカーで処理しています。 したがって、着信要求は、まだ終了していない前の要求を置き換えます。 私たちが今望んでいるのは、リクエストごとに新しいWebワーカーを生成するために小さな変更を加えることです。 それが終わったら、この労働者を殺します。

src/index.jsを開き、Webワーカーを作成する行をボタンのクリックイベントハンドラー内に移動します。 これで、イベントハンドラーは次のようになります。

 btn.addEventListener("click", (e) => { errPar.textContent = ""; const num = window.Number(input.value); if (num < 2) { errPar.textContent = "Please enter a number greater than 2"; return; } const worker = new window.Worker("src/fib-worker.js"); // this line has moved inside the event handler worker.postMessage({ num }); worker.onerror = (err) => err; worker.onmessage = (e) => { const { time, fibNum } = e.data; const resultDiv = document.createElement("div"); resultDiv.innerHTML = textCont(num, fibNum, time); resultDiv.className = "result-div"; resultsContainer.appendChild(resultDiv); worker.terminate() // this line terminates the worker }; });

2つの変更を加えました。

  1. この行をconst worker = new window.Worker("src/fib-worker.js")をボタンのクリックイベントハンドラー内に移動しました。
  2. この行worker.terminate()を追加して、作業が完了したらワーカーを破棄します。

したがって、ボタンをクリックするたびに、計算を処理する新しいワーカーを作成します。 したがって、入力を変更し続けることができ、計算が終了すると、各結果が画面に表示されます。 下のスクリーンショットでは、20と30の値が45の値の前に表示されていることがわかります。しかし、私は最初に45を開始しました。 関数が20と30に戻ると、それらの結果が投稿され、ワー​​カーは終了しました。 すべてが終了したら、[ソース]タブにワーカーが表示されないようにする必要があります。

解雇された労働者とフィボナッチ数を表示
複数の独立した労働者のイラスト。 (大プレビュー)

この記事はここで終了できますが、これがReactアプリの場合、Webワーカーをどのように導入するのでしょうか。 それが次のセクションの焦点です。

ReactのWebワーカー

開始するには、CRAを使用して新しいreactアプリを作成します。 fib-worker.jsファイルをreactアプリのpublic/フォルダーにコピーします。 ここにファイルを置くことは、Reactアプリがシングルページアプリであるという事実に由来します。 これが、reactアプリケーションでのワーカーの使用に固有の唯一のことです。 ここから続くものはすべて純粋なReactです。

src/フォルダーにhelpers.jsファイルを作成し、そこからordinal_suffix()関数をエクスポートします。

 // src/helpers.js export const ordinal_suffix = (num) => { // 1st, 2nd, 3rd, 4th, etc. const j = num % 10; const k = num % 100; switch (true) { case j === 1 && k !== 11: return num + "st"; case j === 2 && k !== 12: return num + "nd"; case j === 3 && k !== 13: return num + "rd"; default: return num + "th"; } };

このアプリでは、いくつかの状態を維持する必要があるため、別のファイルsrc/reducer.jsを作成し、状態レデューサーに貼り付けます。

 // src/reducers.js export const reducer = (state = {}, action) => { switch (action.type) { case "SET_ERROR": return { ...state, err: action.err }; case "SET_NUMBER": return { ...state, num: action.num }; case "SET_FIBO": return { ...state, computedFibs: [ ...state.computedFibs, { id: action.id, nth: action.nth, loading: action.loading }, ], }; case "UPDATE_FIBO": { const curr = state.computedFibs.filter((c) => c.id === action.id)[0]; const idx = state.computedFibs.indexOf(curr); curr.loading = false; curr.time = action.time; curr.fibNum = action.fibNum; state.computedFibs[idx] = curr; return { ...state }; } default: return state; } };

各アクションタイプを次々に見ていきましょう。

  1. SET_ERROR :トリガーされたときにエラー状態を設定します。
  2. SET_NUMBER :入力ボックスの値をstateに設定します。
  3. SET_FIBO :計算されたFNの配列に新しいエントリを追加します。
  4. UPDATE_FIBO :ここでは、特定のエントリを探し、計算されたFNとその計算にかかった時間を含む新しいオブジェクトに置き換えます。

このレデューサーはまもなく使用します。 その前に、計算されたFNを表示するコンポーネントを作成しましょう。 新しいファイルsrc/Results.jsを作成し、以下のコードを貼り付けます。

 // src/Results.js import React from "react"; export const Results = (props) => { const { results } = props; return ( <div className="results-container"> {results.map((fb) => { const { id, nth, time, fibNum, loading } = fb; return ( <div key={id} className="result-div"> {loading ? ( <p> Calculating the{" "} <span className="bold"> {nth} </span>{" "} Fibonacci number... </p> ) : ( <> <p> Time: <span className="bold">{time} ms</span> </p> <p> <span className="bold"> {nth} </span>{" "} fibonnaci number:{" "} <span className="bold"> {fibNum} </span> </p> </> )} </div> ); })} </div> ); };

この変更により、以前のindex.htmlファイルをjsxに変換するプロセスが開始されます。 このファイルには1つの責任があります。計算されたFNを表すオブジェクトの配列を取得し、それらを表示します。 以前との唯一の違いは、ロード状態の導入です。 したがって、計算が実行されているときに、ロード状態を表示して、何かが起こっていることをユーザーに知らせます。

src/App.js内のコードを更新して、最後のピースを入れましょう。 コードはかなり長いので、2つのステップで実行します。 コードの最初のブロックを追加しましょう。

 import React from "react"; import "./App.css"; import { ordinal_suffix } from "./helpers"; import { reducer } from './reducer' import { Results } from "./Results"; function App() { const [info, dispatch] = React.useReducer(reducer, { err: "", num: "", computedFibs: [], }); const runWorker = (num, id) => { dispatch({ type: "SET_ERROR", err: "" }); const worker = new window.Worker('./fib-worker.js') worker.postMessage({ num }); worker.onerror = (err) => err; worker.onmessage = (e) => { const { time, fibNum } = e.data; dispatch({ type: "UPDATE_FIBO", id, time, fibNum, }); worker.terminate(); }; }; return ( <div> <div className="heading-container"> <h1>Computing the nth Fibonnaci number</h1> </div> <div className="body-container"> <p className="error"> {info.err} </p> // ... next block of code goes here ... // <Results results={info.computedFibs} /> </div> </div> ); } export default App;

いつものように、私たちは輸入品を持ち込みます。 次に、useReducerフックを使用して状態とアップデーター関数をインスタンス化します。 次に、関数runWorker()を定義します。この関数は、数値とIDを受け取り、Webワーカーを呼び出してその数値のFNを計算するように設定します。

ワーカーを作成するために、相対パスをワーカーコンストラクターに渡すことに注意してください。 実行時に、Reactコードはpublic/index.htmlファイルに添付されるため、同じディレクトリでfib-worker.jsファイルを見つけることができます。 計算が完了すると( worker.onmessageによってトリガーされます)、 UPDATE_FIBOアクションがディスパッチされ、その後ワーカーは終了します。 私たちが今持っているものは、以前のものと大差ありません。

このコンポーネントのreturnブロックでは、以前と同じHTMLをレンダリングします。 また、計算された数値配列をレンダリングのために<Results />コンポーネントに渡します。

returnステートメント内にコードの最後のブロックを追加しましょう。

 <div className="input-div"> <input type="number" value={info.num} className="number-input" placeholder="Enter a number" onChange={(e) => dispatch({ type: "SET_NUMBER", num: window.Number(e.target.value), }) } /> <button className="btn-submit" onClick={() => { if (info.num < 2) { dispatch({ type: "SET_ERROR", err: "Please enter a number greater than 2", }); return; } const id = info.computedFibs.length; dispatch({ type: "SET_FIBO", id, loading: true, nth: ordinal_suffix(info.num), }); runWorker(info.num, id); }} > Calculate </button> </div>

入力にinfo.num onChange変数を更新します。 ボタン上で、 onClickイベントハンドラーを定義します。 ボタンがクリックされると、数値が2より大きいかどうかがチェックされますrunWorker()を呼び出す前に、計算されたFNの配列にエントリを追加するアクションを最初にディスパッチすることに注意してください。 ワーカーがジョブを終了すると更新されるのはこのエントリです。 このようにして、以前とは異なり、すべてのエントリがリスト内での位置を維持します。

最後に、以前のstyles.cssのコンテンツをコピーして、 App.cssのコンテンツを置き換えます。

これですべてが整いました。 次に、Reactサーバーを起動して、いくつかの数字を試してみてください。 UXの改善である読み込み状態に注意してください。 また、1000までの数値を入力して[計算]をクリックしても、UIの応答性が維持されることに注意してください。

ワーカーがアクティブなときにロード状態を表示します。
読み込み状態とアクティブなWebワーカーを表示しています。 (大プレビュー)

ロード状態とアクティブなワーカーに注意してください。 46番目の値が計算されると、ワーカーが強制終了され、ロード状態が最終結果に置き換えられます。

  • このReactアプリのソースコードはGithubで入手でき、バージョン管理されたアプリがあります。

結論

ふぅ! 長い道のりだったので、まとめましょう。 Webワーカーのその他の使用方法については、WebワーカーのMDNエントリ(以下のリソースリストを参照)を参照することをお勧めします。

この記事では、Webワーカーとは何か、そしてWebワーカーが解決しようとしている問題の種類について学びました。 また、プレーンJavaScriptを使用してそれらを実装する方法も確認しました。 最後に、ReactアプリケーションにWebワーカーを実装する方法を見ました。

この優れたAPIを利用して、ユーザーにより良いエクスペリエンスを提供することをお勧めします。

その他のリソース

  • Console.time() 、MDNWebドキュメント
  • {JSON}プレースホルダー、公式ウェブサイト
  • Webワーカー、MDNWebドキュメントの使用
  • フィボナッチ数、ウィキペディア
  • 条件付き(三項)演算子、MDNWebドキュメント
  • Document 、Web API、MDNWebドキュメント
  • はじめに、Reactアプリの作成(ドキュメント)
  • Function.prototype.toString() 、MDNWebドキュメント
  • IIFE、MDNWebドキュメント
  • workerSetup.js 、素晴らしいフルスタックチュートリアル、GitHub
  • 「Webワーカーを使用したJavaScriptでの並列プログラミング」、Uday Hiwarale、Medium