JS 非同期実行の原則とコールバックの詳細

JS 非同期実行の原則とコールバックの詳細

1. JSの非同期実行の原則

JavaScript はシングルスレッドですが、ブラウザはマルチスレッドであることはご存じのとおりです。シングルスレッド実行タスクは、1 つずつキューに入れる必要があります。タスクの実行に時間がかかる場合 (ajax に時間がかかるなど)、応答がなくなり、後続のタスクは実行を待機することになります。ここで非同期性が作用します。

非同期性を理解するには、まずブラウザに JS エンジン スレッド、イベント トリガー スレッド、GUI レンダリング スレッドという 3 つの基本的な常駐スレッドがあることを知っておく必要があります。

JS エンジン スレッドとイベント トリガー スレッドは一緒にイベント ループ メカニズムを構成し、GUI レンダリング スレッドと JS エンジンは相互に排他的です。JS エンジンが実行されると、GUI スレッドは中断され、GUI の更新はキューに保存され、JS エンジンがアイドル状態のときにすぐに実行されます。

イベント ループ メカニズムから分析します。

JS エンジン スレッドは、同期タスクと非同期タスクに分かれています。

1. すべての同期タスクはメインスレッドを通じて実行され、実行スタックを形成します。

2. 非同期タスクがある場合、非同期プロセス (WebAPI) に引き渡されます。これには、イベント トリガー スレッドまたはタイマー スレッド処理が含まれ、タスク キューが形成されます。

3. 実行スタック内のすべてのタスクが処理され、メインスレッドがアイドル状態になると、タスクはタスクキューから抽出され、実行スタックで実行されます。

簡単に言えば、JavaScript にはメイン スレッドに加えてタスク キューもあります。タスク キューには、非同期で実行する必要があるコンテンツが格納されます。メイン スレッドが実行されると、キューが空になるまでタスク キュー内のタスクが継続的にスキャンされ、実行されます。

画像の説明:

図に示すように、Xiao Ming は学習に時間がかかり、終了しないと DNF ゲームをプレイできないため、学習を非同期タスク キューに入れます。ゲーム (メイン スレッド) を終了してから、学習 (タスク キュー) を行います。この期間中、母親は学習イベント(DOM イベント)を追加します。Xiao Ming は学習タスクを完了するたびに、完了するまで他のタスクがないか確認します(ループスキャン)。

別の例を見てみましょう (ブラウザが更新され、ボタンが継続的にクリックされます)。

  myData = null とします
  //ajaxリクエスト関数ajax() {
  //Tencent COVID-19 リアルタイムデータインターフェース、学習専用 axios.get('https://api.inews.qq.com/newsqa/v1/query/inner/publish/modules/list?modules=chinaDayList,chinaDayAddList,nowConfirmStatis,provinceCompare')
   .then(データ => {
   console.log("ajax は正常に返されました");
   myData = データ.データ
   コンソールにログ出力します。

   })
   .catch(エラー => {
   console.log("ajax の戻りに失敗しました");
   })
  }
  コンソールにログ出力します。
  アヤックス()
  タイムアウトを設定する(() => {
  console.log('タイマー');
  }, 2000);
  コンソールにログ出力します。
  const btn = document.querySelector('button')
  btn.onclick = () => {
  console.log("クリックされました");
  }

ヌル
ヌル
ajaxは成功を返します
物体
タイマーをクリックしました

ご覧のとおり、コンソールはメインスレッドで同期的に実行され、最初に実行されますが、メインスレッド外のタスク キューには、setTimeout、ajax、DOM イベントという非同期的に実行されるコンテンツが格納され、タスク キュー (ループ スキャン キュー) の順序で実行されます。

なぜループでスキャンする必要があるのでしょうか?

クリック イベントからわかるように、ユーザーが操作すると (クリック イベント、スクロール イベント、ウィンドウ サイズ変更イベントなど)、新しいイベントがイベント ループ内のタスク キューに追加され、実行を待機するため、循環スキャンが必要になります。

2. JS 非同期コールバック

非同期操作はすべて最後のタスク キューで実行されるため、多くのロジックの実装は困難です。この時点で、この非同期ロジックを処理する必要があります。最も一般的な方法は、コールバック (コールバック) です。

コールバック関数: 簡単に言えば、関数 A が関数 B をパラメータとして渡すと、関数 B は関数 A によって実行されるコールバック関数になります。コールバックには、ネストされたコールバックとチェーンされたコールバックの 2 種類があります。

コールバックの簡単な使用法は次のとおりです。

   myData = null とします
   コンソールにログ出力します。
   タイムアウトを設定する(() => {
    console.log('タイマー');
   }, 2000);
   const btn = document.querySelector('button')
   btn.onclick = () => {
    console.log("クリックされました");
   }
   名前を「張三」とする
   関数hr(コールバック) {
    タイムアウトを設定する(() => {
     console.log(`私は${name}です`);
     折り返し電話();
    }, 2001);
   }
   コンソールにログ出力します。
   関数gj() {
    console.log(`${name} こんにちは、私はLi Siです。お互いを知りましょう`);
   }
   時間(gj)

ヌル
ヌル
タイマーをクリックしました。私は張三です。こんにちは、李思です。お互いを知りましょう。クリックしました

関数がデータを使用する必要がある場合、コールバックが使用されることは明らかです。ここでは、非同期コールバックが使用されています。

コールバックは非同期性を解決するための一般的な方法ですが、JS の要件はますます複雑になっています。同期と非同期では、ロジックを実装するためにますます多くのコールバックが必要になります。同期操作と非同期操作の混在、および過度のコールバックのネストとインデントにより、コードの解釈と保守が困難になり、「コールバック地獄」が形成されます。

例を見てみましょう:

const verifyUser = function(ユーザー名, パスワード, コールバック){
  dataBase.verifyUser(ユーザー名、パスワード、(エラー、ユーザー情報) => {
    if (エラー) {
      コールバック(エラー)
    }それ以外{
      dataBase.getRoles(ユーザー名、(エラー、ロール) => {
        (エラー)の場合{
          コールバック(エラー)
        }それ以外 {
          dataBase.logAccess(ユーザー名、(エラー) => {
            (エラー)の場合{
              コールバック(エラー);
            }それ以外{
              コールバック(null、userInfo、roles);
            }
          })
        }
      })
    }
  })
};

ほとんどの人は、上記のコードを見ただけで頭が凍りつくでしょう。プロジェクトにこのようなコード ブロックが何百もあると、しばらくすると、それを書いた本人でさえ頭痛がすると思います。自分のプロジェクトに来るのは地獄に来るようなものです。

最も重要なことは、同時に、コールバックによって実行制御がサードパーティ (ajax など) に渡されるため、信頼性の問題があることです。信頼の問題を解決するには、コールバックによって発生する信頼の問題を解決するためのさまざまなロジックをプログラム内に記述する必要があります。

早すぎる電話

·通話完了

呼び出し回数が多すぎるか少なすぎるため、必要なパラメータがコールバック関数に正常に渡されません。

起こりうるエラーは無視されます。

特定の信頼問題を解決するために特定のロジックを記述すると、アプリケーション自体の価値よりも困難さが大きくなり、冗長なコードや可読性の低さなどの問題も発生することがわかります。

要約すると、コールバックは非同期の問題を解決します。

1) タスク処理における人間の論理的思考に適合しない

2) コールバックによって生じる信頼の問題。

コールバックの欠点がますます明らかになったことを受けて、ES6 では非同期の問題を解決するために Promise が更新されました。次の記事では、ES6——Promise について書きます。

要約する

JS 非同期実行原理とコールバックに関するこの記事はこれで終わりです。より関連性の高い JS 非同期実行原理コールバックのコンテンツについては、123WORDPRESS.COM の以前の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • シングルスレッドJavaScriptにおける非同期処理実装の詳細な説明
  • JSシングルスレッド非同期IOコールバックの特性を分析する
  • Javascript 非同期プログラミング: Promise を本当に理解していますか?
  • JavaScript 非同期プログラミングにおける Promise の初期の使用法の詳細な説明
  • 最新の JavaScript で非同期タスクを書く方法
  • Node.js の非同期ジェネレータと非同期反復の詳細な説明
  • 1 つの記事で Node.js の非同期プログラミングを学ぶ
  • Node.js における非同期プログラミングの知識ポイントの詳細な説明
  • JS の 3 つの主要な問題、非同期性とシングルスレッドについて簡単に説明します。

<<:  mysql5.7.18 解凍バージョンで mysql サービスを起動します

>>:  Centos7 での Rsync+crontab 定期同期バックアップ

推薦する

Vue は zip ファイルのダウンロードを実装します

この記事の例では、Vueの具体的なコードを共有し、zipファイルをダウンロードして参考にしています。...

MySQL のインデックスの種類と基本的な使用例

目次索引- 総合索引- ユニークなインデックス- 主キーインデックス- 複合インデックス- 全文索引...

シンプルなドラッグ効果を実現するjs

この記事では、簡単なドラッグ効果を実現するためのjsの具体的なコードを参考までに共有します。具体的な...

MySQLデータをOracleに移行する正しい方法

mysql データベースには student テーブルがあり、その構造は次のとおりです。 Oracl...

MySQL の null 可能フィールドは NULL に設定する必要がありますか、それとも NOT NULL に設定する必要がありますか?

MySQL を頻繁に使用する人は、次のような状況に遭遇する可能性があります。 1. フィールド タ...

JavaScript オブジェクトの組み込みオブジェクト、値型、参照型の説明

目次物体オブジェクト定義オブジェクトのメンバーを反復処理するJS組み込みオブジェクト数学オブジェクト...

CSS レスポンシブ レイアウト システムの例コード

レスポンシブ レイアウト システムは、今日の一般的な CSS フレームワークではすでに非常に一般的で...

Vue はカスタム「モーダル ポップアップ ウィンドウ」コンポーネントのサンプル コードを実装します

目次序文レンダリングサンプルコード要約する序文ダイアログ ボックスは非常に一般的なコンポーネントであ...

nginx アンチホットリンクおよびアンチクローラー設定の詳細な説明

新しい設定ファイルを作成します (たとえば、nginx インストール ディレクトリの下の conf ...

vue3+ts+EsLint+Prettier 標準コード実装

目次使用EsLintの使用プロフィールを追加するPrettierの使用huskyとlint-stag...

JS で Websocket ベースのマルチターミナル ブリッジング プラットフォームを実装する方法

目次1. デバッグ対象2. WebSocketの機能3. ソケット接続を確立する3.1 部屋の作成方...

CSS が最初のサイクルで画像を読み込むために @keyframes を使用するときに発生するホワイトギャップの問題 (フラッシュ画面) をすばやく解決します。

問題の説明: CSS アニメーション プロパティを使用すると、ループが最初に読み込まれたときに白いギ...

WeChatアプレット開発の実践スキル:データの転送と保存

日々の開発で遭遇した様々な問題と、その解決策を閲覧しながら、日々の開発でよく使用するスキルや知識ポイ...

MySQL 子テーブルで外部キー制約チェックを無効にする方法

準備する:教師テーブルと生徒テーブルを定義し、生徒テーブルで教師テーブルIDを参照します。テーブルt...

MySQLの場合の使用例分析

まず、データベース テーブルを作成します。 テーブル `t_demo` を作成します ( `id` ...