JavaScript シングルスレッドと非同期の詳細

JavaScript シングルスレッドと非同期の詳細

序文:

JavaScriptsingle threadedasynchronous性質について考えると、多くの学生は「これは矛盾ではないのか?」と疑問に思わずにはいられません。実際、シングルスレッドと非同期は、同時に言語の特性となることはできません。 js はシングルスレッド言語を選択したため、それ自体は非同期にできませんが、js のホスト環境 (ブラウザー、 Nodeなど) はマルチスレッドであり、ホスト環境によって js は何らかの方法で非同期プロパティを持つようになります (イベント駆動型、これについては後述します)。下を見てみると、js のメカニズムがいかにシンプルで効率的であるかが分かります。

ブラウザ:

js はシングルスレッド言語です。ブラウザは js にタスク (関数) を実行するためのメインスレッドを 1 つだけ割り当てますが、一度に実行できるタスクは 1 つだけです。これらのタスクは、実行待ちのタスク キューを形成します。ただし、ネットワーク リクエスト、タイマー、イベント監視など、フロントエンドの一部のタスクは非常に時間がかかります。他のタスクと同様に順番待ちにすると、実行効率が非常に低くなり、ページがフリーズする原因にもなります。そのため、ブラウザは、主に http リクエスト スレッド、ブラウザ タイミング トリガー、ブラウザ イベント トリガー スレッドなど、時間のかかるタスクのために追加のスレッドを開きます。これらのタスクは非同期です。次の図はブラウザのメインスレッドを示しています。

1. タスクキュー

ブラウザはネットワーク リクエストなどの非同期タスク用に別のスレッドを開くと述べましたが、メイン スレッドはこれらの非同期タスクが完了したことをどうやって知るのでしょうか。答えはコールバック関数です。プログラム全体はイベント駆動型であり、各イベントは対応するコールバック関数にバインドされます。たとえば、タイマーを設定するコードがあります。

setTimeout(関数(){
    console.log(タイムアウト);
}, 50);


このコードが実行されると、ブラウザは非同期でタイミング操作を実行します。50ms に達すると、タイミング イベントがトリガーされます。このとき、コールバック関数がタスク キューに配置されます。プログラム全体はこのようなイベントによって推進されます。
したがって、js は常にシングルスレッドであり、ブラウザは非同期を実装するものです。

メインスレッドに戻ります:

js は、タスク キューからタスクを抽出し、メイン スレッドに入れて実行するという 1 つのジョブを実行しています。これをさらに詳しく見てみましょう。

今学んだ概念を図に当てはめてみましょう。上で述べたブラウザが非同期タスク用に別途開くスレッドは、 WebAPIsとして統一的に理解できます。上で述べたタスク キューはcallback queueです。ここで言うメイン スレッドは点線で構成されている部分です。 heapstack一緒になって js メイン スレッドを構成します。関数の実行は、スタックをプッシュおよびポップすることで実現されます。例えば、図には foo() 関数があります。メイン スレッドはこれをスタックにプッシュします。関数本体を実行すると、上記の関数を実行する必要があることがわかったので、これらの関数は再びスタックにプッシュされます。関数が実行されると、関数はスタックからポップされます。スタックが空の場合、タスクが完了したことを意味します。このとき、次のタスクがcallback queueで見つかり、スタックにプッシュされます (この検索プロセスは、タスク キューにタスクがあるかどうかを常にループして確認するため、イベント ループと呼ばれます)。

2. 混乱を招く問題を説明する

1. setTimeout(f1,0)とは何ですか?

このステートメントに関する最大の疑問は、f1 がすぐに実行されるかどうかです。答えは必ずしもそうではありません。次のコードに示すように、メイン スレッド内のコマンドが実行されたかどうかによって決まるためです。

setTimeout(関数(){
コンソールログ(1);
},0);
コンソールログ(2);

2. Ajax リクエストは非同期ですか?

上記の内容を理解すると、 ajaxリクエストは非同期であることがわかります。リクエストが完了すると、リクエスト完了イベントがトリガーされ、コールバック関数がcallback queueに配置されます。メイン スレッドがコールバック関数を実行するときは、シングル スレッドのままです。

3. インターフェースレンダリングスレッドは別のスレッドです

インターフェースレンダリングスレッドは、別途開かれたスレッドです。DOM が変更されるとすぐにインターフェースが再レンダリングされるということですか?

DOM が変更されるとすぐにインターフェイスが再レンダリングされると、効率が必然的に非常に低くなります。そのため、ブラウザのメカニズムでは、インターフェイス レンダリング スレッドとメイン スレッドが相互に排他的であると規定されています。メイン スレッドがタスクを実行する場合、ブラウザ レンダリング スレッドは一時停止状態になります。

3. ブラウザの非同期メカニズムの使い方

js は常に単一のスレッドで実行されており、ブラウザは時間のかかる問題を解決するために、明らかに時間のかかるタスクごとに個別のスレッドを設定していることはすでにわかっています。ただし、これらの明らかに時間のかかる問題に加えて、自分で作成したプログラムにも時間のかかる機能がある場合があります。この状況にどう対処すればよいでしょうか。確かに、自分で別のスレッドを開くことはできませんが、ブラウザによって開かれたウィンドウを使用することはできます。ブラウザ タイマー スレッドとイベント トリガー スレッドは使いやすいですが、ネットワーク リクエスト スレッドは適していません。詳しく見てみましょう:

時間のかかる関数が f1 であり、f1 が f2 の先行タスクであると仮定します。

タイマーを使用してスレッドをトリガーします。

関数 f1(コールバック){
setTimeout(関数(){
    // f1 コードコールバック();
},0);
}
f1(f2);

この書き方は結合度が高いです。

イベントを使用してスレッドをトリガーします。

$f1.on('custom',f2); //ここでバインディングイベントはjQuery関数f1(){として記述されます
setTimeout(関数(){
    // f1 のコード$f1.trigger('custom');
},0);
}


このメソッドは、カスタム イベントをバインドすることでメソッド 1 を分離し、異なるイベントをバインドすることで異なるコールバック関数を実装できるようにします。ただし、このメソッドを適用しすぎると、プログラムが読みにくくなります。

4. 非同期の利点と適切なシナリオ

非同期の利点:

例を使って同期と非同期を比較してみましょう。4 つのタスク (番号 1、2、3、4) が​​あり、その実行時間が 10 ミリ秒であるとします。タスク 2 はタスク 3 の先行タスクであり、タスク 2 には 20 ミリ秒の応答時間が必要です。以下で比較してみましょう。非ブロッキング I/O を実装する方法がわかります。

適しているもの:

プログラムが大量の I/O 操作とユーザー要求を必要とする場合、シングルスレッド、非同期、イベント駆動の特性を備えた言語である js が非常に適していることがわかります。マルチスレッド言語と比較すると、システムオーバーヘッドをあまり消費する必要がなく、マルチスレッド管理の処理にエネルギーを費やす必要もありません。同期実行言語と比較すると、ホスト環境の非同期およびイベント駆動メカニズムにより、非ブロッキング I/O を実現できるため、どのようなシナリオに適しているかを知っておく必要があります。

これで、 JavaScriptシングルスレッドと非同期に関する詳細な記事は終了です。JavaScript JavaScriptシングルスレッドと非同期に関するより関連性の高いコンテンツについては、123WORDPRESS.COM で以前の記事を検索するか、次の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • JS の 3 つの主要な問題、非同期性とシングルスレッドについて簡単に説明します。
  • シングルスレッドJavaScriptにおける非同期処理実装の詳細な説明
  • JSシングルスレッド非同期IOコールバックの特性を分析する
  • JavaScript の 3 つの山: シングル スレッドと非同期

<<:  Nginx 502 Bad Gateway エラーの原因と解決策

>>:  HTML でのアンカーポイントの使用_PowerNode Java アカデミー

推薦する

負荷分散と動的・静的分離を実現するNginx+Tomcatの原理の分析

1. Nginx ロードバランシングの実装原理1. Nginxはリバースプロキシを通じて負荷分散を実...

better-scrollプラグインのスライドできないバグについて(2021年プラグインで解決)

より良いスクロールの原則親コンテナーであるため、ラッパーの高さはコンテンツのサイズに応じて増加します...

MySQL 8.0.2 オフラインインストールと設定方法のグラフィックチュートリアル

MySQL_8.0.2のオフラインインストール方法は参考までに。具体的な内容は以下のとおりです。次の...

CentOS 6.6 ソースコードのコンパイルと MySQL 5.7.18 のインストールチュートリアルの詳細な説明

1. ユーザーとグループを追加する1. mysqlユーザーグループを追加する # グループ追加mys...

HTMLフローティングプロンプトボックス機能の実装コード

一般的なフォーム プロンプトは常にフォームのスペースを占有し、フォームが長くなったり広くなったりして...

Docker イメージのプルとタグ操作 pull | tag

Fabric プロジェクトのソースコードを読み直してみたところ、Docker の部分でよくわからな...

CSS で画像アダプティブ コンテナを実装するいくつかの方法 (要約)

多くの場合、画像をコンテナのサイズに合わせて調整する必要があります。 1. imgタグ方式幅と高さを...

LinuxでifconfigとaddrがIPアドレスを表示できない問題を解決する

1. 仮想マシンにLinuxシステムをインストールし、仮想マシンを起動し、rootとパスワードを入力...

Tomcat は親の委任メカニズムを破壊して Web アプリケーションの分離を実現します。

目次Tomcat クラスローダー階層WebAppクラスローダー共有クラスローダーカタリナクラスローダ...

Linux でジャンクファイルをエレガントに削除する方法

あなたも私と同じように、コンピューターのファイルを整然と整理し、不要なファイルを適宜削除するプログラ...

React イベントバインディングの詳細

目次クラスコンポーネントイベントバインディング関数コンポーネントイベントバインディング要約するRea...

yum 経由で CentOS に PHP をインストールするチュートリアル

まず、yumを使ってCentOSにPHPをインストールする方法を紹介します。 1. PHPのyumソ...

MySQL 10進数符号なし更新負数を0に変換

今日、インターフェースの同時実行の問題を検証したところ、これまでredisで解決していた同時実行のプ...

MySQL 8.0 のタイムゾーン問題を解決する手順

ソフトウェアバージョンウィンドウズ: ウィンドウズ10 MySQL: mysql-8.0.16-wi...

Vue ファースト スクリーン パフォーマンス最適化コンポーネントの知識ポイントの概要

Vue ファースト スクリーン パフォーマンス最適化コンポーネントVue ファースト スクリーン パ...