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クライアントがログインできない問題の解決方法

推薦する

Windows DNS サーバーに「ワームレベル」の脆弱性が露呈、17 年間存在

脆弱性の紹介SigRed の脆弱性はワーム化可能であるため非常に危険です。つまり、ユーザーの介入なし...

Docker: /etc/default/docker の DOCKER_OPTS パラメータを変更しても反映されない

デフォルトでは、 /etc/default/docker 設定は有効になりません。docker 環境...

MySQL サーバーの接続、切断、および cmd 操作

mysql コマンドを使用して MySQL サーバーに接続します。 MySQL サーバーが起動したら...

Linux TTY/PTS の違いの概要

キーボードで文字を入力すると、対応するプロセスにどのように送信されるのでしょうか? ps や who...

JavaScript における this ポイントの問題の詳細な説明

要約する地球環境 ➡️ ウィンドウ通常関数 ➡️ ウィンドウまたは未定義コンストラクター ➡️ 構築...

Dockerを使用してMySQL 8.0をデプロイする方法の例

1. 公式サイトを参照してdockerをインストールする2. MySQLイメージをプルします(デフォ...

Linux CentOS インストール JDK および Tomcat チュートリアル

まずJDKをダウンロードします。ここではjdk-8u181-linux-x64.tar.gzを使用し...

mysql5.7.17 zip の解凍とインストールの詳細な手順

1. ダウンロードアドレスhttps://dev.mysql.com/downloads/mysql...

Linuxテキスト処理ツールの詳細な説明

1. /etc/passwdファイル内のデフォルトシェルが/sbin/nologinではないユーザー...

JavaScriptタイマーとボタン効果設定の詳細な説明

タイマー効果: <div> <font id='timeCount'...

WangEditor リッチ テキスト コンポーネントを Angular でカプセル化する方法

リッチ テキスト コンポーネントは、Web プログラムで、特にブログやフォーラムなどの Web サイ...

CentOS 6.x のインストール時に発生するエラー「ディスク sda に BIOS RAID メタデータが含まれています」の解決方法

今日、CentOS6.2 をインストールしていたところ、ハード ドライブの検出段階を通過できませんで...

LinuxでのMySQLのインストール手順

1. mysql tar ファイルをダウンロードします。参考: 2. インストールパッケージがあるデ...

MYSQLでプロシージャの名前を変更する方法の詳細な説明

最近、ストアド プロシージャの名前を変更する機能を使用しました。インターネットで情報を検索しましたが...

MYSQL(電話番号、IDカード)データ非感応化の実装

1. データ感度低下の説明日常の開発ニーズでは、データの感度低下が頻繁に発生します。たとえば、ID ...