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 からエクスポートされた scv ファイル内の文字化けやジャンプ行の問題をすばやく解決します

仕事上の理由により、完全なオンライン化(​​つまり、すべてのデータがオンラインで完了し、インポートや...

Ubuntu 18.04 に mysql5.7.23 をインストールするチュートリアル

この記事では、Ubuntu18.04にmysql5.7.23をインストールする具体的な方法を参考まで...

DockerでMySQLマスタースレーブ環境を構築する方法の詳しい説明

序文この記事では、docker-compose と dockerfile を使用して、binlog ...

Webpack4プラグインの実装原理についての簡単な説明

目次序文知る練習すれば完璧になる序文wabpack では、ローダーの他にプラグインがコア機能です。プ...

Nginx でアンチホットリンクを設定するための手順を完了する

必要:通常、サイト側は、ウェブサイト上の動画や写真が盗まれるのを防ぎたいと考えています。結局のところ...

Mysqlは隣接リスト(隣接リスト)を通じてツリー構造を保存します。

以下の内容では、隣接リストを使用してツリー構造を保存する MYSQL のプロセスとソリューションを紹...

Linux でバックグラウンド タスクを実行するために nohup と screen を使用する例と違いの簡単な分析

SSH ターミナル (putty、xshell など) を使用して Linux サーバーに接続し、時...

MySQL 5.7 のパフォーマンスと sys スキーマの監視パラメータの説明 (推奨)

1. パフォーマンス スキーマ: はじめにMySQL 5.7 では、多数の新しい監視項目の導入、ス...

MySQLチュートリアルDMLデータ操作言語の例の詳細な説明

目次1. データ操作言語 (DML) 2. データを追加する(挿入) 3. 既存のテーブルをコピーし...

MySQL InnoDB のロック機構の詳細な説明

前面に書かれたデータベースは本質的に共有リソースであるため、同時アクセスのパフォーマンスを最大化する...

mysqlは時間を自動的に追加し、時間を自動的に追加および更新する操作を実装します

時間フィールドは、データベースの使用時によく使用されます。よく使われるのは作成時間と更新時間です。し...

MySQL カーソルの原理と使用例の分析

この記事では、例を使用して MySQL カーソルの原理と使用方法を説明します。ご参考までに、詳細は以...

Vueのsync修飾子の詳細な説明

目次1. 手順2. 修飾語3. .sync 修飾子4. まとめ1. 手順指示とは命令です。文字通りの...

Linux bzip2 コマンドの使用

1. コマンドの紹介bzip2 は、ファイルの圧縮と解凍に使用されます。これは、Linux システム...

MySQL マルチバージョン同時実行制御 MVCC の詳細な研究

MVCC MVCC (Multi-Version Concurrency Control) は、マル...