JavaScript はマルチスレッド化できますか? JavaScript のタイミングメカニズムについての深い理解_JavaScript スキル

WBOY
リリース: 2016-05-16 17:53:31
オリジナル
782 人が閲覧しました

たとえば、

コードをコピーします コードは次のとおりです。

setTimeout( function(){ alert('Hello !') } , 0);
setInterval( callbackFunction , 100);

これはそうではないため、setTimeout の挨拶メソッドがすぐに実行されると考えられます。突然そう言われましたが、JavaScript API ドキュメントでは、2 番目のパラメーターの意味を、コールバック メソッドが実行されるまでのミリ秒数として明確に定義しています。これが 0 ミリ秒に設定されている場合、当然すぐに実行されます。 🎜>同様に、setInterval の callbackFunction メソッドが 100 ミリ秒ごとに実行されることは間違いありません。

しかし、JavaScript アプリケーション開発の経験が増え続けると、ある日、次のようになります。奇妙なコード部分があり、あなたは困惑しています:

コードをコピー コードは次のとおりです:
div.onclick = function(){
setTimeout( function(){document.getElementById ('inputField').focus();},
}; 0 ミリ秒後に実行されるのに、なぜ setTimeout を使用するのでしょうか?

という確固たる信念が、昨日まで誤って



コードをコピーします
コードは次のとおりです: setTimeout( function(){ while(true){} } , 100); setTimeout(function(){alert('Hello!'); } , 200); setInterval(
);
コードの最初の行は無限ループに入りますが、すぐに 2 行目と 3 行目が期待したものではなく、アラートの挨拶が表示されず、callbacKFunction からのニュースがないことがわかります。

現時点では、あなたはこの状況を受け入れるのが難しいです。長年確立されてきた認識を変えて新しいアイデアを受け入れるプロセスは苦痛を伴うものですが、事実は目の前にあり、JavaScript の真実を探求する必要があります。それは痛みのためではありません。そして、JavaScript スレッドとタイマーを探索する旅を始めましょう。

雲を開けて月明かりを見てみましょう

上記の誤解の主な理由は次のとおりです。 : JavaScript エンジンは複数のスレッドを実行しており、JavaScript のタイマー コールバック関数は非同期で実行されていると無意識に信じています。

実際、JavaScript はほとんどの場合、バックライトの必要性を欺くために目隠しメソッドを使用します。ここで明確にしておきます。事実:

JavaScript エンジンは単一のスレッドで実行され、ブラウザーでは常に 1 つのスレッドだけが JavaScript プログラムを実行します。

これは、 JavaScript エンジンをシングルスレッドで実行すると、スレッドの同期などの複雑な問題を気にする必要がなく、問題が単純化されます。

では、シングルスレッドの JavaScript エンジンはどのように連携するのでしょうか。ブラウザ カーネルはこれらのタイマーを処理し、ブラウザ イベントに応答しますか?
以下はブラウザ カーネルの処理方法と組み合わせた簡単な説明です。

ブラウザ カーネルの実装により、これらのスレッドはそれぞれ非同期で実行できます。その他、同期を維持するためにカーネル制御下にあるもの ブラウザ カーネルに少なくとも 3 つの実装がある場合 常駐スレッド: JavaScript エンジン スレッド、インターフェイス レンダリング スレッド、ブラウザ イベント トリガー スレッド これらに加えて、実行後に終了するスレッドもいくつかあります。 HTTP リクエスト スレッド。これらの非同期スレッドは、さまざまな非同期イベントを生成します。これは、シングル スレッドの JavaScript エンジンが他のスレッドとどのようにやり取りし、通信するかを示す図です。各ブラウザ カーネルの実装の詳細は異なりますが、呼び出しの原則は似ています。
JavaScript はマルチスレッド化できますか? JavaScript のタイミングメカニズムについての深い理解_JavaScript スキル
画像からわかるように、ブラウザの JavaScript エンジンはイベント駆動型であることがわかります。ここでのイベントは、ブラウザによって割り当てられたさまざまなタスクとみなすことができます。タスクを追加するための setTimeout の呼び出しなど、JavaScript エンジンによって現在実行されているコード ブロックから発生するものもありますが、インターフェイス要素のマウス クリック イベント、スケジュールされたトリガー時間の到着通知、非同期リクエスト ステータスなど、ブラウザー カーネルの他のスレッドから発生することもあります。コードの観点から見ると、タスク エンティティはさまざまなコールバック関数であり、JavaScript エンジンはタスク キューへのタスクの到着を待機しています。単一スレッドの関係のため、これらのタスクはキューに入れられ、処理される必要があります。

上の図 t1 ~ t2..tn はさまざまな時点を表し、tn の下の対応する小さな点はその時点のタスクを表しているとします。エンジンは t1 に対応するタスク ブロック コードで実行されています。この時点で、ブラウザ カーネル内の他のスレッドのステータスを説明します。

t1 時間:

GUI レンダリング スレッド。 :

このスレッドは、ブラウザ インターフェイスの HTML 要素をレンダリングする役割を果たします。このスレッドは、インターフェイスの再描画 (再描画) が必要な場合、または何らかの操作によってリフローが発生した場合に実行されます。 JavaScript のタイミング メカニズムを説明する場合、このスレッドと JavaScript エンジンのスレッドは相互に排他的であるため、この時点でレンダリング スレッドについて説明する必要があります。これは、JavaScript スクリプトがこれらの If 要素を変更するときに操作できるためです。要素の属性が同時にインターフェイスをレンダリングすると、レンダリング スレッドの前後で取得された要素データが矛盾する可能性があります。

JavaScript エンジンがスクリプトを実行している間、ブラウザのレンダリング スレッドは一時停止状態になります。

したがって、ノードの追加、ノードの削除、ノードの外観の変更など、スクリプト内で実行されたインターフェイスの更新は、すぐには反映されません。キュー内では、JavaScript エンジンはアイドル状態のときにレンダリングする機会があります。

GUI イベント トリガー スレッド:

JavaScript スクリプトの実行は、 html 要素のイベント。図からわかるように、JavaScript エンジン スレッドでは、ユーザーが最初にマウス ボタンをクリックします。イベントは他のスレッドによってタスク キューの最後に非同期で送信されます。エンジン t1 のタスクが処理されており、このマウス クリック イベントは処理を待機しています。

タイミング トリガー スレッド:

ここでのブラウザ モデルのタイミング カウンタは、JavaScript エンジンによってカウントされないことに注意してください。これは、JavaScript エンジンがブロックされたスレッド状態にある場合、時間をカウントすることができないためです。

図からわかるように、セグメント内の t1 の時点で、マウス クリック イベントがトリガーされた後、この時点で、JavaScript エンジンの場合、タイミング トリガー スレッドが非同期タイミング イベントを生成し、そのイベントがクリック イベントのキューに入れられます。
同様にt1期間中に、次にsetIntervalタイマーも追加されますので、t1期間内に2回連続でイベントがキューイングされます。処理されるキュー

期間 t1 が非常に長く、setInterval のタイミング間隔よりもはるかに大きい場合、タイミング トリガー スレッドは非同期タイミング イベントを継続的に生成し、イベントが実行されたかどうかに関係なく、タスク キューの最後に配置されることがわかります。処理されますが、スケジュールされたイベントの前のタスクが処理された後、これらの配置内のスケジュールされたイベントは中断されることなく次々に実行されます。これは、JavaScript エンジンの場合、処理中の各タスクが中断されるためです。

t1 の後、つまり現在処理されているタスクが返された後、JavaScript エンジンはタスク キューをチェックし、それが見つかった場合はタスク キューを確認します。現在のキューが空ではない場合、t2 で対応するタスクが実行用に取り出されます。以下の観点から、以下のとおりです。

キューが空でない場合、エンジンは次のことを行います。タスクが処理されるまでキューの先頭からタスクを取り出します。つまり、エンジンはタスクが返される前に次のタスクを実行します。

は実行できません。これで、JavaScript がマルチスレッド化できるかどうかを明確に理解できたと思います。また、JavaScript タイマーの動作メカニズムも理解できたと思います。いくつかのケースを分析してみましょう:

ケース 1: setTimeout と setInterval
コードをコピーします コードは次のとおりです:

setTimeout(function( ){
/* コード ブロック... */
setTimeout(arguments.callee,
}, 10);

setInterval(){
/ *コードブロック... */
} , 10);

これら 2 つのコードは一緒に見えますが、最初の段落のコールバック関数の setTimeout は、実行後に新しい setTimeout を設定します。理論的には、前のコールバック処理の完了から次のコールバック処理の開始までの時間間隔が 10 ミリ秒以上あると仮定します。2 番目の期間は setInterval の後に定期的にトリガーされます。理論的には、スレッドは 10 秒ごとに非同期タイミング イベントを生成し、それらをタスク キューの最後に置きます。

ケース 2。 : ajax 非同期リクエスト それは本当に非同期ですか?

JavaScript は単一スレッドで実行されると言われているため、実際には、XMLHttpRequest は接続後の非同期ですか?リクエストは確かに非同期ですが、このリクエストは新しいスレッドを開くためにブラウザによって行われます (上の図を参照)。コールバックが事前に設定されている場合、非同期スレッドはステータスの変更を生成します。タスクが処理されると、JavaScript エンジンは常に単一スレッドでコールバック関数、具体的には単一スレッドで onreadystatechange で設定された関数を実行します。
関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート