今回はブラウザのマルチスレッド機構について詳しく解説していきます。 ブラウザのマルチスレッド機構を使用する際の注意点について、実際の事例を見てみましょう。
話をする前に、js は単一のスレッドに基づいており、このスレッドがブラウザーの js エンジンであることは誰もが知っています。
まず、誰もがブラウザで使用しているスレッドを見てみましょう。
大きな画像の読み込みなど、時間のかかる操作を実行したい場合は、待機プロセス中にユーザーを待たせるためのプログレスバーが必要になる場合があります。その場合、コード全体がブロックされます。現時点では、これらの時間のかかる操作を処理するワーカー スレッドが必要になる可能性があります。従来の HTML 時代には基本的にこれを実現することは不可能でしたが、今ではワーカーと呼ばれるものが存在します。これは js のクラスであり、使用するにはインスタンスを作成するだけで済みます。
var worker = new Worker(js file path);
関数パラメータを構築 js ファイルのパスを入力します。この js ファイルはブラウザの新しく開かれたスレッドで実行され、元の js エンジン スレッドには影響しません。
では、これらは互いに影響を及ぼさないので、2 つのスレッドはどのように通信するのでしょうか? 答えは、実際にはすでにコード内にあります。つまり、onPostMessage と onmessage の 2 つの関数です。ここで、onPostMessage (data) のパラメーターは次のとおりです。渡したいデータ、onmessage はコールバック関数 です。Onmessage には、event.data という隠しパラメータがあります。メインスレッドを更新します。
ただし、JavaScript アプリケーションでの経験としては、開発は増え続け、充実し続けますが、ある日、あなたは奇妙なものを発見します。 コードは不可解です:[javascript] プレーンコピーの表示?
setTimeout( function(){ alter('Hello!'); } , 0);
- setInterval( callbackFunction , 100);
- 同様に、setInterval の callbackFunction メソッドも 100 ミリ秒ごとに即時に実行されます
これは何も考えずに言われたものではないため、setTimeout の挨拶メソッドはすぐに実行されると考えられていますが、JavaScript API ドキュメントでは 2 番目のパラメーターの意味を、コールバック メソッドが実行されるまでのミリ秒数として明確に定義しています。ここでは 0 ミリ秒に設定されていますが、もちろんすぐに実行されます
[javascript]
view plain copy print?p.onclick = function(){
setTimeout( function(){document.getElementById( 'inputField').focus();},
}; 0 ミリ秒後に実行されるのに、なぜ setTimeout を使用するのでしょうか? 、確固たる信念が揺らぎ始めました。
最後まである日、あなたは誤って悪いコードを書いてしまいました:- [javascript]
プレーンコピー印刷を表示しますか?
setTimeout( function(){ while(true){} } , 100);
setTimeout( function(){alert('Hello!'); } , 200);
setInterval( callbackFunction , 200);
コードの最初の行は無限ループに入りますが、すぐに 2 行目と 3 行目が期待したものと異なっており、警告メッセージが表示されず、callbacKFunction からのニュースがないことがわかります。 !
現時点では、あなたはこの状況を受け入れるのが難しいです。長年確立されてきた認識を変えて新しいアイデアを受け入れるプロセスは苦痛を伴うものですが、事実はあなたの前にあり、JavaScript の真実を探求する必要があります。ではありません。痛みのため停止します。JavaScript のスレッドとタイマーを探索する旅を始めましょう
雲を開けて月を見ましょう
上記のすべての誤解の主な理由は、JavaScript エンジンには複数の機能があると潜在的に信じているためです。スレッドが実行されており、JavaScript のタイマー コールバック関数が非同期で実行されます
実際、JavaScript はほとんどの場合、私たちの目を欺くために、目をくらませるメソッドを使用しています。この事実は、次のとおりです。
JavaScript エンジンが実行されています。ブラウザは常に 1 つのスレッドだけで JavaScript プログラムを実行します
また、単一のスレッドでは、次のような複雑な問題を気にする必要がありません。スレッド同期として、問題は単純化されます。
では、シングルスレッド JavaScript エンジンはどのようにブラウザ カーネルと連携して、これらのタイマーを処理し、ブラウザ イベントに応答するのでしょうか?
以下は、ブラウザ カーネルの処理方法に基づいた簡単な説明です。
ブラウザ カーネルの実装では、複数のスレッドが非同期で実行できます。特定のブラウザ カーネルの実装に少なくとも 3 つの常駐スレッドがある場合、これらのスレッドはカーネル制御の下で相互に連携します: JavaScript エンジン スレッド、インターフェイス レンダリング スレッド、ブラウザ イベント トリガー スレッドに加えて、HTTP リクエスト スレッドなど、実行後に終了するスレッドもいくつかあります。次の図は、シングルスレッド JavaScript エンジンがどのように対話し、通信するかを示しています。各ブラウザーのカーネルの実装の詳細は異なりますが、呼び出し原理は似ています
図からわかるように、ブラウザーの JavaScript エンジンはイベント駆動型です。ここでは、そのさまざまなタスクは、JavaScript エンジンによって現在実行されているコード ブロック (タスクを追加するための setTimeout の呼び出しなど)、またはブラウザー カーネルの他のスレッド (インターフェイス要素のマウス クリックなど) から発生する可能性があります。イベント、時間指定トリガー、時間到着通知、非同期リクエスト ステータス変更通知など。コードの観点から見ると、タスク エンティティはさまざまなコールバック関数です。これにより、JavaScript エンジンはタスク キュー内のタスクの到着を待機します。 -スレッドの関係では、これらのタスクはキューに入れられ、エンジンによって次々に処理されます。 上の図の T1 ~ t2..tn は、異なる時点を表します。 tn の下にある対応する小さな四角は、その時点のタスクを表します。時刻 t1 で、t1 に対応するタスク ブロック コードでエンジンが実行されているとします。この時点で、ブラウザ カーネル内の他のスレッドのステータスを説明します。 GUI レンダリング スレッド:
このスレッドは、ブラウザ インターフェイスHTML 要素
のレンダリングを担当します。インターフェイスを再描画する必要がある場合 ( Repaint )、または特定の操作によってリフローが発生した場合に、このスレッドが実行されます。この記事では JavaScript のタイミング メカニズムの説明に重点を置いていますが、このスレッドと JavaScript エンジンのスレッドは相互に排他的であるため、この時点でレンダリング スレッドについて説明する必要があります。JavaScript スクリプトは DOM 要素を操作できるため、理解しやすいです。これらの要素のプロパティを変更し、同時にインターフェイスをレンダリングすると、レンダリング スレッドの前後で取得された要素データが不一致になる可能性がありますJavaScript エンジンがスクリプトを実行している間、ブラウザのレンダリング スレッドは実行されます。サスペンド状態、つまり「フリーズ」です GUI イベント トリガー スレッド:
JavaScript スクリプトの実行は、t1 期間中に、ユーザーが最初にマウス ボタンをクリックすると、ブラウザのイベント トリガー スレッドによってキャプチャされ、マウス クリック イベントを形成します。図からわかるように、JavaScript エンジンの場合、スレッド的には、このイベントは他のスレッドによってタスク キューの最後に非同期で送信されます。エンジンは t1 でタスクを処理しているため、このマウス クリック イベントは処理を待っています。
タイミング トリガー スレッド:
ここでブラウザ モデルのタイミングに注意してください。JavaScript エンジンはシングルスレッドであるため、カウンターはカウントされません。スレッドがブロックされた状態にある場合、時間をカウントできません。タイミングの計時とトリガーは外部に依存する必要があるため、キュー内のタイミング イベントも非同期イベントになります。図からわかるように、マウス クリック イベントがトリガーされた後、t1 の期間中、この時点で、JavaScript エンジンの場合、タイミング トリガー スレッドは非同期タイミング イベントを生成し、それをタスク キューに入れ、クリック イベント コールバックの後にキューに入れられ、処理を待ちます。
同様に、まだ t1 期間内ですが、setInterval タイマーも追加され、インターバル タイミングであるため、t1 期間内に 2 回連続してトリガーされ、これら 2 つのイベントはキューの最後にキューイングされます。期間 t1 が非常に長く、setInterval タイミング間隔よりもはるかに大きい場合、タイミング トリガー スレッドは非同期タイミング イベントを継続的に生成し、それらをタスクの最後に配置することがわかります。処理されているかどうかはわかりませんが、t1 より前のタスクと最初のスケジュールされたイベントが処理されると、これらのキュー内のスケジュールされたイベントは中断されることなく順番に実行されます。これは、JavaScript エンジンの場合、処理キュー内の各タスクが中断されるためです。も同様に処理されますが、処理の順序が異なります。
t1 の後、つまり現在処理されているタスクが返された後、JavaScript エンジンはタスク キューをチェックし、現在のキューが空ではないことを確認します。 t2 の下にある対応するタスクを取り出して実行する、などの観点から:キューが空でない場合、エンジンはキューの先頭からタスクを取り出します。タスクは処理されます。つまり、エンジンは戻った後も実行を続けます。タスクの場合、タスクが戻る前にキュー内の他のタスクを実行することはできません。
ケース 1: setTimeout と setIntervalこれで、JavaScript が使用できるかどうかが明確に理解できたと思います。マルチスレッドであり、JavaScript タイマーの動作メカニズムについても理解します。以下で説明します。分析のためのいくつかのケース:
[javascript] view plain copy print?
setTimeout(function(){
/* コードブロック... */
setTimeout(arguments.callee, 10);
}, 10);
setInterval(function(){- /*コード ブロック... */
- }, 10); これら 2 つのコードは同じように見えますが、実際には異なります。最初の段落のコールバック関数は、JavaScript エンジンの実行後に新しい setTimeout タイミングを設定します。 理論的には、前のコールバックの完了から次のコールバックの開始までの時間間隔は、setInterval でタイミングを設定した後、2 つの setTimeout コールバック間の実行時間間隔が 10 ミリ秒以上であると仮定します。タイミング トリガー スレッドは 10 秒ごとに起動し続けます。秒ごとに非同期の時間イベントを生成し、それをタスク キューの最後に置きます。理論的には、2 つの setInterval コールバック間の実行時間間隔は 10 秒以下です。
ケース 2:非同期 ajax リクエストは本当に非同期ですか?
JavaScript は単一スレッドで実行されると言われているため、接続後の XMLHttpRequest は本当に非同期ですか?
実際、このリクエストは行われます。リクエストのステータスが変化したときに、ブラウザによって新しいスレッド リクエストが開かれます (上の図を参照)。コールバックが事前に設定されている場合、非同期スレッドは状態変更イベントを生成し、それを JavaScript エンジンの処理キューに入れます。タスクが処理されると、JavaScript エンジンは常に単一スレッドでコールバック関数を実行します。具体的には、onreadystatechange で設定された関数は依然として単一スレッドで実行されます。- このメソッドは習得できたと思います。この記事の事例を読んだ後は、PHP 中国語 Web サイトの他の関連記事にも注目してください。 推奨読書:
以上がブラウザのマルチスレッド機構の詳しい説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。