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 5.7 以降のバージョンのダウンロードとインストールのグラフィック チュートリアル

1. ダウンロード1. MySQL公式サイトのダウンロードアドレス: https://downloa...

カルーセルの制作方法を実現するjs

この記事では、カルーセル画像の表示を実現するためのjsの具体的なコードを参考までに共有します。具体的...

仕事の効率を上げるJS略語スキル20選

目次複数の変数を同時に宣言する場合は、1 行に短縮できます。分割代入は複数の変数に同時に値を割り当て...

フローティングをクリアするいくつかの方法(推奨)

1. 同じタイプの空の要素を追加し、要素の CSS 属性 clear:both; を設定します。 ...

パズル効果を実現するネイティブ js

この記事では、パズル効果を実現するためのネイティブjsの具体的なコードを参考までに共有します。具体的...

JS を使って 1 分で github+Jekyll ブログに訪問カウント機能を追加する実装

目次1分でgithub+Jekyllブログにトラフィック機能を追加する1. ジェクルとは何か1. J...

Chromeブラウザの自動パスワード保存プロンプト機能を無効にする方法

注: Web 開発では、フォームに autocomplete="off" を追加...

Node.js で簡単なクローラーケースを作成するチュートリアル

準備まず、nodejs をダウンロードする必要がありますが、これは問題ないはずです。原文はwebst...

Lvs+Nginx クラスターを使用して高並列アーキテクチャを構築する例

目次1. Lvsの紹介2. Lvs負荷分散モード2.1 NAT 2.2 ターン2.3 DRモード3....

Mongodb の GUID 表示の問題の詳細な分析

問題を見つける最近、プログラムのストレージを Mongodb に移行したところ、Guid 型が書き込...

JavaScriptはシンプルな計算機能を実装します

この記事では、参考までに、簡単な計算機を実装するためのJavaScriptの具体的なコードを紹介しま...

Vue のリスナーの基本的な使用例

目次序文1. リスナーの基本的な使い方2. リスナー形式3. ページに入るとすぐに監視とディープモニ...

XHTML の一般的な構造タグ

構造本文、見出し、HTML、タイトル文章abbr、頭字語、アドレス、引用ブロック、br、引用、コード...

Intelli Idea で Tomcat 設定が見つからない問題の解決方法

2日前に新しい会社に入社しました。その会社ではIntelli Ideaを使っています。Eclipse...

Windows での mysql-5.7.28 のダウンロード、インストール、および構成に関する詳細なグラフィックとテキストのチュートリアル

最近MySQLデータベースのバージョンを変更する必要があり、それを記録するために記事を書きます1. ...