js はシングルスレッドですが、なぜ非同期操作を実行できるのでしょうか?
これは、ブラウザ (js のホスト環境) が何らかの方法で js に非同期属性を持たせるという事実に帰着します。
プロセスとスレッドを区別します:
プロセス: 実行中のアプリケーション。各プロセスには独自の独立したメモリ空間があります。たとえば、開いているブラウザはプロセスです。
スレッド: 独立したプロセスのサブセット。スレッドは共有メモリ空間で実行されます。
ブラウザはマルチプロセスです。以下に示すように:
#そして、ページが開かれるたびに、独立したプロセスが作成されます。プロセスには独自のマルチスレッドがあります。ブラウザが単一プロセスの場合、特定のページがクラッシュすると、ブラウザ全体に影響します。
ブラウザにはどのようなプロセスがあるか:
1. ブラウザ: ブラウザのメインプロセス (調整と制御を担当) があります。 1 つだけで、その機能は次のとおりです。
• ブラウザ インターフェイスの表示とユーザー対話を担当します。前方、後方など。
• 各ページの管理、他のプロセスの作成と破棄を担当します。
• レンダラー プロセスによって取得されたメモリにビットマップを描画し、ユーザーに提供します。インターフェイス
• ネットワーク リソース、ダウンロードなどの管理
##2. サードパーティのプラグイン プロセス: 各タイプのプラグインはプロセスに対応しており、このプロセスは、プラグインが使用されます 3 、GPU プロセス: 最大 1 つ、3D 描画などに使用されます。 4、ブラウザ レンダリング プロセス (ブラウザ カーネル) (レンダラー) (レンダラー)、 は内部的にマルチスレッドです ) デフォルトでは、各タブ ページには 1 つのプロセスがあり、相互に影響しません。主な機能: ページのレンダリング、スクリプトの実行、イベント処理など。
ブラウザのレンダリング プロセス (ブラウザ カーネル) に含まれるスレッド:
1 、GUI レンダリング スレッド• ブラウザ インターフェイスのレンダリング、HTML、CSS の解析、DOM ツリーと RenderObject ツリーの構築、レイアウトと描画などを担当します。 • インターフェイスを再描画 (Repaint) する必要がある場合、または何らかの操作によってリフローが発生した場合、このスレッドが実行されます。 •GUI レンダリング スレッドは何も行わないことに注意してください。 JS エンジンとのスレッドは相互に排他的です。JS エンジンが実行されると、GUI スレッドは一時停止されます (凍結と同等)。GUI の更新はキューに保存され、JS エンジンがアイドル状態になるとすぐに実行されます。 2. JS エンジン スレッド (
「JavaScript エンジン」は通常、仮想マシンと呼ばれます。JS カーネルとも呼ばれ、JavaScript スクリプト プログラムの処理を担当します。(V8 エンジンなど) )
• JS エンジン スレッドは、JavaScript スクリプトの解析とコードの実行を担当します。
• JS エンジンは、タスク キュー内のタスクの到着を待機し、それらを処理します。タブ ページ (レンダラー プロセス) が実行されるたびに、JS プログラムを実行する JS スレッドは 1 つだけです。
• また、GUI レンダリング スレッドと JS エンジン スレッドは相互に排他的であるため、JS の実行時間が長すぎる場合にも注意してください。 、ページのレンダリングに一貫性がなくなり、ページのレンダリングと読み込みがブロックされます。
3. イベント トリガー スレッド
• JS エンジンではなくブラウザーに属し、イベント ループを制御するために使用されます (JS エンジン自体がビジー状態であることは理解できます。ブラウザは支援のために別のスレッドを開く必要があります)
• JS エンジンが setTimeOut (ブラウザ カーネルの他のスレッド (マウス クリック、AJAX 非同期リクエストなど) から送信されることもあります)、対応するタスクがイベント スレッドに追加されます。
• 対応するイベントがトリガー条件を満たした場合、対応するタスクがイベント スレッドに追加されます。トリガーされると、スレッドは保留キューの最後にイベントを追加し、JS エンジンによる処理を待ちます。
• 注: JS のシングルスレッド関係により、保留キュー内のイベントはJS エンジンによる処理を待機するためにキューに入れる必要があります (JS エンジンがアイドル状態のときに実行されます)
4. タイミング トリガー スレッド
• 伝説の setInterval と setTimeout が存在するスレッド
• ブラウザのタイミング カウンタは JavaScript エンジンによってカウントされません (JavaScript エンジンはシングルスレッドであるため、スレッドがブロックされた状態にある場合、タイミングの精度に影響します)
• したがって、別のスレッドを使用してタイミングを計り、タイミングをトリガーします (タイミングが完了すると、スレッドはイベント キューに追加され、実行前に JS エンジンがアイドル状態になるのを待ちます)
• W3C は HTML 標準で規定しており、setTimeout の 4ms 未満の時間間隔は 4ms としてカウントすることが規定されていることに注意してください。新しいスレッドリクエストはブラウザを通じて開かれます
• 状態変化が検出されたとき、コールバック関数が設定されている場合、非同期スレッドは状態変化イベントを生成し、コールバックをイベント キューに入れます。その後、JavaScript エンジンによって実行されます。
GUI レンダリング スレッドと JS エンジン スレッドは相互に排他的です:
JavaScript は DOM を操作できるため、DOM の属性を変更すると、これらの要素をインターフェイスで同時にレンダリングすると (つまり、JS スレッドと UI スレッドが同時に実行されます)、レンダリング スレッドの前後で取得された要素データが不一致になる可能性があります。したがって、予期しないレンダリング結果を防ぐために、ブラウザは GUI レンダリング スレッドと JS エンジンが相互に排他的な関係になるように設定し、JS エンジンが実行されると GUI スレッドが一時停止され、GUI の更新がファイルに保存されます。 JS エンジンまでキューに入れます。スレッドがアイドル状態になるとすぐに実行されます。
js の実行メカニズム: js はシングルスレッドです。関数が実行されるたびに、関数はスタックにプッシュされます。ただし、非同期操作がある場合は、ブラウザー スレッド (webAPI) が処理し、キューでは、メインスレッド(実行スタック)の実行が完了した時点で、タスクキューにタスクがあれば実行されます。
これが、次のコードが最初に b を出力し、次に a を出力する理由です。 settimeout 関数はタスク キューに配置され、console.log('b') がメイン スレッドになります。
setTimeout(() => { console.log('a'); }, 0); console.log('b');
この記事は js チュートリアル 列から引用したものです。ぜひ学習してください。
以上がJavaScript 実行メカニズムに関する簡単な説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。