ByteDance インタビュー: JS を使用して Ajax 同時リクエスト制御を実装する方法

ByteDance インタビュー: JS を使用して Ajax 同時リクエスト制御を実装する方法

序文

正直に言うと、最近とても混乱していると感じています。テクノロジーと人生について。また、将来の発展のためのアイデアを得るために、大企業の多くの友人とも話をしました。また、面接や採用時に面接者に尋ねられるいくつかの質問についても話しました。たまたま長い間インタビューを受けてなかったので、その中からいくつか選んでみました。いくつかのインタビューの質問の分析シリーズが近日中に公開される予定です。

今日はByteDanceからのお知らせです。

次の要件を満たすバッチ リクエスト関数 multiRequest(urls, maxNum) を実装します。

• 同時接続の最大数maxNumが必要です

• リクエストが返されるたびに、新しいリクエストを追加するためのスロットが空けられます

• すべてのリクエストが完了すると、URLの順に結果が出力されます。

多くの学生がこの質問をある程度見たことがあると思います。以下では、シナリオ、問題分析、最終的な実装を段階的に説明し、この質問の完全な分析をシンプルでわかりやすい方法で提供しようとします。

シナリオ

次のようなシナリオがあるとします。送信する必要のある非同期リクエストが 30 個ありますが、何らかの理由で、同時リクエストの数を 5 未満に制御し、応答結果をできるだけ早く取得する必要があります。

何をすべきでしょうか?

まず、Ajax のシリアルと並列の性質について見てみましょう。

Promise.all に基づくシリアルおよび並列 Ajax の実装

通常、非同期リクエストは Promise に基づいてカプセル化されますが、ここでは主に非同期リクエストに焦点を当てます。

  • シリアル: 1つの非同期リクエストが完了すると、次のリクエストが行われます
  • 並列処理: 複数の非同期リクエストが同時に処理される

いくつかの promise インスタンスを定義して、シリアル/パラレルを具体的に示します。

シリアル

var p = 関数() {
  新しいPromise(function(resolve,reject))を返す{
    タイムアウトを設定する(() => {
      コンソールログ("1000");
      解決する();
    }, 1000);
  });
};
var p1 = 関数() {
  新しいPromise(function(resolve,reject))を返す{
    タイムアウトを設定する(() => {
      コンソールログ("2000");
      解決する();
    }, 2000);
  });
};
var p2 = 関数() {
  新しいPromise(function(resolve,reject))を返す{
    タイムアウトを設定する(() => {
      コンソールログ("3000");
      解決する();
    }, 3000);
  });
};

p()
  .then(() => {
    p1() を返します。
  })
  .then(() => {
    p2() を返します。
  })
  .then(() => {
    console.log("終了");
  });

例に示すように、シリアルは対応するインターフェース要求を上から下へ実行します。

平行

通常、複数の非同期プロセスの後にコードが実行されるようにする必要がある場合は、以下を使用します。

Promise.all((promises: [])).then((fun: function));
Promise.all は、then コールバックを実行する前に、promises 配列内のすべての promise オブジェクトが解決済み状態に到達することを保証します。

var promises = 関数 () {
  [1000, 2000, 3000].map((現在) => { を返します。
    新しいPromise(function(resolve,reject))を返す{
      タイムアウトを設定する(() => {
        console.log(現在の値);
      }、 現在);
    });
  });
};

Promise.all(promises()).then(() => {
  console.log("終了");
});

Promise.all 同時実行制限

ここで、promises 配列内の各オブジェクトが HTTP リクエストであり、そのようなオブジェクトが数十万ある場合のシナリオを考えてみましょう。

何が起こるかというと、瞬時に数十万の HTTP リクエストが送信されるため、無数のコール スタックが蓄積され、メモリ オーバーフローが発生する可能性があります。

このとき、Promise.all の同時実行制限を考慮する必要があります。

Promise.all の同時実行制限は、各瞬間に同時に実行される Promise の数が固定され、最終的な実行結果が元の Promise.all と一致することを意味します。

タイトルの実装

思考分析

プロセス全体は再帰呼び出しを使用して実装されます。最初に送信されるリクエストの数は最大許容数に制限され、これらの各リクエストは完了時に再帰的に送信され続ける必要があります。URL 内の特定の URL は渡されたインデックスによって決定され、最終的な出力順序が混乱することなく順番に出力されるようにします。

コードの実装

関数 multiRequest(urls = [], maxNum) {
  //リクエストの合計数 const len ​​= urls.length;
  // リクエスト数に基づいてリクエスト結果を保存する配列を作成します。const result = new Array(len).fill(false);
  // 現在完了した数 let count = 0;

  新しい Promise を返します ((resolve, reject) => {
    // maxNum をリクエストします while (count < maxNum) {
      次();
    }
    関数 next() {
      現在の値を count++ とします。
      // 境界条件を処理する if (current >= len) {
        // すべてのリクエストが完了したら、Promise を成功状態に設定し、結果を Promise 値として返します。result.includes(false) && resolve(result);
        戻る;
      }
      const url = urls[現在の];
      console.log(`start ${current}`、新しいDate().toLocaleString());
      フェッチ(url)
        .then((res) => {
          // リクエスト結果を保存します。 result[current] = res;
          console.log(`Completed${current}`, 新しい Date().toLocaleString());
          // リクエストが完了していない場合は、if (current < len) {を再帰します。
            次();
          }
        })
        .catch((エラー) => {
          console.log(`${current}` の終了、新しい Date().toLocaleString());
          結果[現在] = err;
          // リクエストが完了していない場合は、if (current < len) {を再帰します。
            次();
          }
        });
    }
  });
}

要約する

JS を使用して Ajax 同時リクエスト制御を実装する方法に関する ByteDance インタビューに関するこの記事はこれで終わりです。Ajax 同時リクエスト制御の JS 実装に関する関連コンテンツについては、123WORDPRESS.COM の以前の記事を検索するか、次の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM を応援していただければ幸いです。

以下もご興味があるかもしれません:
  • JavaScript で Promise を使用して同時リクエスト数を制御する方法
  • JavaScript/TypeScript で同時リクエスト制御を実装するためのサンプルコード
  • JavaScript を使用して同時実行制御を実装するためのサンプル コード
  • js非同期インターフェースの同時実行数を制御する方法の例
  • Nodejs クローラーの高度なチュートリアル 非同期同時実行制御
  • Nodejs 実践体験: 同時実行を制御するイベントプロキシモジュール
  • JavaScript で同時実行制御を実装する方法

<<:  git bash を使用して Linux にログインするための ssh の設定方法

>>:  mysql8.0.11クライアントがログインできない問題の解決方法

推薦する

特定のシンボルで複数の行と列に分割するMySQLの例

一部の障害コード テーブルでは、履歴またはパフォーマンス上の理由から、次の設計パターンが使用されます...

Vue ライフサイクルの紹介とフック関数の詳細な説明

目次Vueライフサイクルの紹介とフック機能VUEライフサイクルフックVue ライフサイクルの紹介作成...

MySQL グリーンバージョン設定コードと 1067 エラーの詳細

MySQL グリーンバージョン設定コードと 1067 エラーMySQL エンコーディングを表示 &#...

NavicatがLinuxサーバー上のMySQLに接続できない問題を解決する

最初は悲しい気持ちになりました。スクリーンショットは以下の通りです。 少し苦労しましたが、解決策は次...

CentOS7 での MySQL 8.0.16 のインストールと設定のチュートリアル

MySQLの古いバージョンをアンインストールします(古いバージョンがない場合は、この手順をスキップし...

Windows 10でDockerコンテナのポートにアクセスできない問題に対する完璧な解決策

Windows 10 で Docker コンテナのポートにアクセスできない問題を解決する (ポート ...

Vue codemirrorはオンラインコードコンパイラの効果を実現します

序文Web 上でオンライン コード コンパイルの効果を実現したい場合は、 CodeMirrorを再度...

Ubuntu 20.04 LTS で Java 開発環境を構成する

Java開発キットjdkをダウンロードするJDK のダウンロード アドレスはhttp://www.o...

測定画像HTTPリクエスト

一般的なブラウザでテスト ページを開き、Fiddler で http リクエストを表示してください。...

MySQL 8.0.12 インストール グラフィック チュートリアル

MySQL8.0.12 インストールチュートリアルをみんなで共有します。 1. インストール1.イン...

独自のネイティブ JavaScript ルーターを作成する方法

目次序文導入JavaScript 履歴 API独自のネイティブJSルーティングを実装するHistor...

Linuxカーネルの浮動小数点演算のサポートに関する簡単な説明

現在、ほとんどの CPU は浮動小数点ユニット (FPU) をサポートしています。FPU は、プロセ...

無料のパブリック STUN サーバー

無料のパブリック STUN サーバーSIP 端末がプライベート IP アドレスを使用する場合、スタン...

MySQLの日付と時刻の間隔計算の分析例

この記事では、例を使用して、MySQL の日付と時刻の間隔計算について説明します。ご参考までに、詳細...

ES6実装クラスのプライベート変数の書き方をいくつか詳しく説明します

プライベート変数のクロージャ実装プライベート変数は共有されないnew キーワードにより、 perso...