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 indexof関数の使用手順

以下のように表示されます。 LOCATE(部分文字列、文字列)文字列 str 内の部分文字列 sub...

CSS でテキストカラーグラデーションを実装する 3 つの方法

Web フロントエンド開発のプロセスでは、UI デザイナーはグラデーション テキストを使用したデザイ...

VMWare仮想マシンにCentOS7システムをインストールする詳細な手順

インストール前の作業: VMware Workstation がインストールされていることを確認し、...

Vant Uploaderは1枚以上の写真をアップロードするコンポーネントを実装します

この記事では、1枚以上の写真をアップロードするためのVant Uploaderコンポーネントを紹介し...

MySQL における引用符とバックティックの違いと使い方の詳細な説明

序文そこでこのブログを書きました。このブログでは大物の記事からいくつかの知識も推奨しています。侵害が...

Maxwell を使用して MySQL データをリアルタイムで同期する方法

目次マクスウェルについてMaxwellの設定と使用1. Maxwellインストールパッケージをダウン...

フレックスレイアウトとposition:absolute/fixedの競合の詳細な説明

以前、プロジェクトを開発しているときに、flex レイアウトと position:absolute/...

Mysqlマスタースレーブ同期の実装原理

1. MySQL マスター/スレーブ同期とは何ですか?マスター データベースのデータが変更されると、...

Vue はタブ ラベルを実装します (ラベルが自動スクロールを超える)

作成されたタブラベルがページの表示領域を超えると、タブラベルの距離だけ自動的にスクロールされます。ま...

JavaScript の new 演算子を自分で実装する方法

目次コンストラクタ新しいオペレーター自分で新しいものを実装するコンストラクタnew を導入する前に、...

HTML テーブルインライン形式の詳細な説明

インライン形式<colgroup>...</colgroup>属性名 属性値...

VUEをベースにしたシンプルな学生情報管理システムの実装

目次1. 主な機能2. 実装のアイデア3. コードの実装4. エフェクト表示V. 結論1. 主な機能...

アイデアを通じてプロジェクトをDockerにパッケージ化する方法

多くの友人が、Docker でプロジェクトを実行する方法をずっと知りたがっていました。今日は、自分の...

埋め込みJavaScriptと外部リンクの基本的な応用方法

目次埋め込みJavaScriptと外部リンクの基本的な応用JavaScript の記述方法には、イン...

Docker 経由で CentOS コンテナを作成する手順

目次序文コンテナ間の通信を容易にするためのブリッジネットワークを作成するCentOS7イメージを使用...