リクエスト数を制限するために Ajax 同時リクエストを実装するために js を使用するサンプル コード

リクエスト数を制限するために Ajax 同時リクエストを実装するために js を使用するサンプル コード

問題の説明: 非同期リクエストの数が不確定な場合、数百の http リクエストが瞬時に発生したときに無数のコール スタックが蓄積され、メモリ オーバーフローの問題が発生するのを防ぐためです。

要件: 同時リクエストの数を一度に 3 未満に制限し、応答結果をできるだけ早く取得します。

同じ面接の質問:

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

  • 同時接続の最大数maxNumが必要です
  • リクエストが返されるたびに、新しいリクエストを追加するためのスロットが開いたままになります。
  • すべてのリクエストが完了すると、結果が URL の順に出力されます。

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

通常、非同期リクエストは Promise に基づいてカプセル化されます。

シリアル: 1つの非同期リクエストが完了すると、次のリクエストが行われます

並列処理: 複数の非同期リクエストが同時に処理される

例: シリアル

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(() => {
 コンソールログ('終了')
})

平行:

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

Promise.all(promises()).then(() => {
 コンソールログ('終了')
})

Promise.all(promises: []).then(fun: function);

promise.allは、thenコールバックを実行する前に、配列内のすべてのpromiseオブジェクトが解決された状態に到達することを保証します。

Promise.all 同時実行制限

意味: 各時点で同時に実行される Promise の数は固定されており、最終的な実行結果は元の Promise.all と一致したままになることを意味します。

アイデアと実装

これは、再帰呼び出しとリクエストの最大数の設定を使用して実装されます。そして、これらのリクエストはそれぞれ完了すると再帰的に送信され続け、urls内の特定の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) {を再帰します。
      次();
     }
    });
  }
 });
}

コード実装:

  // タスクリスト->新しいタスク uploadFile() {
   _this = this とします。
   var アップロードスレッド制限数 = 3,
    アップロードスレッド数 = 0、
    送信完了数 = 0、
    結果終了数 = 0;
   var マーク = 0;
   var タスク = [];
   var アップロード = 関数 () {
    (アップロードスレッド数 < アップロードスレッド制限数){
     (sendFinishNum >= _this.fileList.length)の場合{
      結果完了数 >= _this.fileList.length の場合 {
       creatTask(); // リクエストを完了する}
      戻る;
     }
     (関数(j) {
      item = _this.fileList[j]とします。
      p = new FormData();
      p.append("ファイル", 項目);
      タスク.push(
       アクシオス({
        メソッド: "post",
        url: `${window.UL_CONFIG.BASEURL}/api/files/upload`,
        データ: p,
        onUploadProgress: (progressEvent) => {
         (let i in _this.rowData) {
          _this.rowData[i].name === アイテム.name
           ? (_this.rowData[i].percent = Math.round(
             (progressEvent.loaded / progressEvent.total) * 100
            ))
           : "";
         }
        },
       })
        .then((res) => {
        /* obj = {} とします。
         obj.url = `${window.UL_CONFIG.BASEURL}/api/files/${res.data}`;
         obj.fileName = アイテム名;
         obj.fmt = _this.ruleForm.format;
         obj.samplingRate = _this.ruleForm.samplingRate;
         fileUrls.push(obj); */
        })
        .catch((e) => {
           ? (_this.rowData[i].パーセント = 0)
         _this.$notify.error({
          タイトル: 「エラー」、
          メッセージ:「サービス接続エラー」+ item.name +「アップロードに失敗しました」
         });
        .finally(() => {
         アップロードスレッド数--;
         結果終了数++;
         アップロード();
      );
     })(送信完了番号);
     アップロードスレッド数++;
     送信完了番号++;
    }
   };
   var createTask = 関数 () {
    axios.all(タスク).then((res) => {
     //新しいアップロードタスクを作成する/* let fd1, fd2, calcFlag, flagArr, language;
     fd1 = {};
     flagArr = Object.assign([], _this.ruleForm.checkList);
     if (_this.ruleForm.recognize == "自動認識") {
      flagArr.push("2");
     calcFlag = flagArr.reduce(
      (accu, curr) => 数値(accu) + 数値(curr)
     );
     _this.ruleForm.recognize == "自動的に認識する"
      ? (言語 = "")
      : (言語 = _this.ruleForm.recognize);
     fd1.processContent = calcFlag;
     fd1.remark = _this.ruleForm.remark;
     fd1.name = _this.ruleForm.taskName;
     fd1.fmt = _this.ruleForm.format;
     fd1.サンプリングレート = _this.ruleForm.サンプリングレート;
     fd1.language = 言語;
     fd1.type = 1; // タイプ: 1 オーディオ、2 ビデオ fd1.files = fileUrls; */
     newTask(fd1).then((res) => {
      /* _this.cmpltBtnState = false;
      _this.$store.commit("setTaskId", res.data.id);
      _this.submitFailNumber = res.data.submitFailNumber; */
      _this.$parent.dataInit();
     });
    });
   アップロード();
  },

これで、js を使用して同時 Ajax リクエストの数を制限するサンプル コードを実装するこの記事は終了です。js Ajax 同時リクエスト制限の詳細については、123WORDPRESS.COM の以前の記事を検索するか、次の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • js は axios 制限リクエスト キューを実装します
  • JavaScript で Promise を使用して同時リクエスト数を制御する方法
  • gin 投稿リクエストのJSON本文を取得する
  • JSはリクエストディスパッチャーを実装する
  • PHPはChromeフォームのリクエストデータをインターフェースで使用されるJSONデータに変換する機能を実装します。
  • JavaScript 中断要求に対するいくつかの解決策の詳細な説明

<<:  Django+mysql の設定と簡単な操作データベースのサンプルコード

>>:  GNU Parallelの具体的な使用法

推薦する

18 個のキラー JavaScript ワンライナー

序文JavaScript は習得が最も簡単な言語の 1 つであるため、成長と繁栄を続けており、市場に...

ウェブページのカスタム選択ボックス選択

選択ドロップダウン リスト フォームは誰もがよく知っているかもしれませんが、デフォルトのドロップダウ...

HTMLの基本タグと構造の詳細な説明

1. HTMLの概要1.HTML: ハイパーテキスト マークアップ言語。これはプログラミング言語では...

MySQL のロングトランザクション例の詳細な説明

序文: 「MySQL 入門」シリーズの記事は終了しました。今後も引き続き MySQL に焦点を当て、...

フォームの「Enter」、「Submit」、「Enter != Submit」を削除する方法

「Enter != Submit」問題を実装するには、通常、「ボタンの種類」と「入力ボックスの数」か...

MySQLユーザー削除バグを解決する

著者が MySQL を使用してユーザーを追加していたところ、ユーザー名が間違って記述されていることに...

CSSプロパティに基づいたボタンホバーボーダーと背景アニメーションのコレクション

ハートの属性不透明度: .999 は要素のスタッキングコンテキストを作成し、ボタン6と8のアニメーシ...

Windows でのシンプルな Mysql バックアップ BAT スクリプトの共有

序文この記事では、Windows で Mysql をバックアップするための簡単な BAT スクリプト...

WeChatミニプログラム開発のためのコンポーネント設計仕様

WeChat ミニプログラム コンポーネント設計仕様コンポーネントベースの開発という考え方は、私の開...

CSS の優先順位に関する詳細な紹介

CSS の優先順位について話す前に、CSS とは何か、CSS が何に使用されるのかを理解する必要があ...

MySQL 8.0 再帰クエリの簡単な使用例

序文この記事では、MySQL 8.0 の新機能を使用して再帰クエリを実装します。詳細なサンプル コー...

MySQL マスタースレーブレプリケーションの原理と注意点

前面に書かれた最近、Mycat で特別なトピックを書いています。最近、多くの友人が面接に出かけている...

HTML テーブル マークアップ チュートリアル (29): セルのライト境界線の色属性 BORDERCOLORLIGHT

セルでは、明るい境界線の色を個別に定義できます。 > 基本構文<TD ボーダーカラーライ...

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

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

CentOS で新しいユーザーを作成し、キーログインを有効にする方法

目次新しいユーザーを作成する新規ユーザーを承認する新規ユーザーのSSHキーログインを有効にする他のS...