JS ベースの Ajax 同時リクエスト制御を実装する方法

JS ベースの Ajax 同時リクエスト制御を実装する方法

序文

最近、インタビューの質問を見ました。もちろん、この記事のタイトルである「Ajax 同時リクエスト制御」ですが、とても興味深いと思います。コミュニティで調べたところ、ByteDance からのインタビューの質問のはずです。多くの大物がこれを要約しています。私はそれらをすべて読んだので、自分で要約してみたいと思います。コードは記事の最後に掲載します。何か間違っている点があれば、指摘してください。

Ajax シリアルおよびパラレル

  • シリアル: 一般的に、次のインターフェースは、前のインターフェースから返されたデータを使用する必要があります。フロントエンドでよく使用されるリクエスト ライブラリは、Promise ベースの HTTP ライブラリである Axios です。これを実現するには、チェーン呼び出しまたは Async Await を直接使用できるため、ここでは説明しません。
  • 並列: 複数のリクエストが同時に発生します。一般的には、すべてのデータを取得した後にページをレンダリングしたり、その他の操作を実行したりするために使用されます。主にPromise.allに基づいています。実装方法は次のとおりです。

上記のシミュレーションはPromise.allに基づく並列操作を実装しており、出力結果は以下のとおりです。

これが終わりであり、存在しないと感じますか?さて、いよいよ本題です。ページが同時に何万ものリクエストを送信し、そのすべてが成功した後にいくつかの操作を実行する必要がある状況を想像してみましょう。結果はどうなるでしょうか?コードを実行できず、メモリがオーバーフローします。残念ながら、ここでこの記事のトピックに戻ります。同時 Ajax リクエストを制御するにはどうすればよいでしょうか?一度に一定数のリクエストだけを出力し、すべてが成功するまで続けるように依頼しました。次に、この操作を 2 つの方法で実装します。読者の皆さんのアドバイスをお待ちしています。

Ajaxの同時リクエスト制御のための2つのソリューション

Promiseベースの再帰

次の 2 つの方法は、どちらも上図の Tasks 配列を必要とします。覚えておいてください。Promise に基づく最初の方法は、次のような考え方です。同時実行プールを渡すと、ワークスペースのプールが作成されます。各ワークスペースは、実行する対応するタスク (リクエスト) を取得し、成功したら保存し、ワークスペースにタスクがなくなるまでタスク (リクエスト) を取得し続けます。もちろん、失敗した場合は直接終了します。これが一般的な考え方です。以下のコードの各行にコメントを付けました。どうぞご了承ください。

クラスベースの実装

2 番目の方法はクラスに基づいています。上記との違いは、この方法ではワークスペースが 1 つしか作成されないことです。基本的な考え方は、タスク (リクエスト) を実行するためのワークスペースを作成し、すべてのタスクをそこにプッシュしますが、毎回、対応する数の同時タスクしか実行できません。同時タスクの数より少ない場合は、タスク (リクエスト) がなくなるまでタスクを取得して実行し続けます。これで完了です。具体的な実装は次のとおりです。

コードショーケース

これら 2 つのメソッドの実装コードを以下に示します。

    const delay = 関数 delay(間隔) {
      新しい Promise((res,rej) => { を返す
        タイムアウトを設定する(() => {
          res(間隔)
        }, 間隔);
      })
    }


    タスクを = [() => {
      戻り遅延(1000)
    },() => {
      返品遅延(1003)
    },() => {
      返品遅延(1005)
    },() => {
      返品遅延(1002)
    },() => {
      返品遅延(1004)
    },() => {
      返品遅延(1006)
    }]

    // Promise.all を通じて並列処理を実装する Promise.all(tasks.map(task => task())).then(res => {
      コンソールログ(res);
    })

    // Promise に基づいて関数 creatRequest(tasks,pool) を実装します {
      // 毎回送信されるリクエストの数はプールによって制御されます
      プール = プール || 5
      // 各リクエストの結果を保存するために使用されます(順番に保存されます)
      結果 = [] とします。
      // together はワークスペースを作成するために使用されます。pool が渡されると、それに応じて複数のワークスペースが作成されます。// つまり、pool の長さと null の値を持つ配列を作成します。together = new Array(pool).fill(null),
      // インデックスは毎回取得されるタスク値です。index = 0;
      一緒に = 一緒に.map(() => {
        // Promise に基づく管理 return new Promise((resolve,reject) => {
          // 関数を作成し、すぐに実行する const run = function run() {
            // タスクプールが空の場合、リクエストが正常に送信されたことを意味します if(index >=tasks.length) {
              解決する()
              戻る 
            }
            // まず、現在の成功したリクエストの結果を保存するためのインデックスを保存します。let old_index = index,
            // 現在送信されているリクエストを取得し、インデックスを累積します。そのため、インデックスは上記に保存されます。 // ここでは、index++ が最初に計算されてから累積されますが、++index はその逆で、最初に累積されてから計算されます。task = tasks[index++];
            // リクエストを実行する task().then(result => {
            // 成功した結果を保存する results[old_index] = result
            // 再帰的に実行を続行します。つまり、タスクをワークスペースに取得して実行を続行します run();
            }).catch(理由 => {
              拒否(理由)
            })
          }
          // すぐにrun()を実行する
        })
      })
      // Promise.all を使用してワークスペースを制御します。つまり、一度に 2 つのリクエストを同時に実行します。 return Promise.all(together).then(() => results)
    }


    createRequest(タスク,2).then(結果 => {
      // 全体が成功するにはすべてが成功する必要があるので、結果を順番に保存します。console.log('success',results);
    }).catch(解決 => {
      // いずれか 1 つでも失敗すると、システム全体が失敗します console.log('failed');
    })



    // クラスに基づいて関数 creatRequest(tasks,pool,callback) を実装します {
      // パラメータの制限と検証 if(typeof pool === 'function') {
        コールバック = プール;
        プール = 5
      }
      if (typeof pool !== 'number') プール = 5
      if (typeof callback !== 'function') callback = function () {}
      //------
      クラスタスクキュー {
        // 実行回数 = 0;
        // すべてのタスクをキューに入れる queue = [];
        // タスク(リクエスト)の実行結果を保存します。 results = [];
        タスクをプッシュします。
          自分 = これ
          // タスクをワークスペースにプッシュします。self.queue.push(task)
          // リクエストを送信するロジックを実行する self.next()
        }
        次() {
          自分 = これ
          // 実行中のタスク数が同時実行数より少ない場合、タスクの実行を継続します while(self.runing < pool && self.queue.length) {
            自己実行++;
            // これはタスクを取得して削除するのと同じです。let task = self.queue.shift();
            // リクエストを実行する task().then(result => {
              //実行結果を保存する self.results.push(result)
            }).finally(() => {
              // 実行中の項目の数をクリアする self.runing--
              // リクエストの実行を続行する self.next()
            })
          }
          // タスクがない場合はループが終了します if(self.runing === 0) callback(self.results)
        }


      }
      // インスタンス化 let TQ = new TaskQueue()
      タスクごとにタスクを実行します。
    }


    リクエストを作成します(タスク、2、結果=> {
      console.log(結果);
    })

要約する

上記は、この一連のインタビューの質問の要約です。私自身もメモしました。今後もフロントエンドの記事を更新し続けます。最後に、フロントエンドの友人全員が学習を継続し、スキルを継続的に向上させることができることを願っています。さあ、若者よ! ! !

JS ベースの Ajax 同時リクエスト制御の実装方法に関するこの記事はこれで終わりです。JS による Ajax 同時リクエスト制御の実装に関するより関連性の高いコンテンツについては、123WORDPRESS.COM の以前の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • リクエスト数を制限するために Ajax 同時リクエストを実装するために js を使用するサンプル コード
  • ByteDance インタビュー: JS を使用して Ajax 同時リクエスト制御を実装する方法

<<:  Nginx セッション損失問題の解決策

>>:  MySql5.x を MySql8.x にアップグレードする方法と手順

推薦する

HTML の順序なしリストタグと順序付きリストタグの使用例

1. 上部と下部のリストタグ: <dl>..</dl>:上dt下層dd: カ...

ウェブサイトのデザイン体験のための7つの異なるカラースキーム

ウェブサイト構築におけるカラーマッチングは非常に特殊であり、ウェブサイトのテーマ、感情、雰囲気などの...

Docker ベースの Redis クラスターの構築方法

Redisイメージをダウンロードする docker pull yyyyttttwww/redis を...

完全なMySQL学習ノート

目次MyISAM と InnoDBパフォーマンスの低下と SQL の速度低下の理由: MySQL 実...

MySQL 8のパスワードを忘れた場合のベストな対処法の簡単な分析

序文MySQL に精通している読者は、MySQL が非常に迅速に更新されることに気付くかもしれません...

mysql のインデックスと FROM_UNIXTIME に関する問題

ゼロ、背景今週の木曜日にたくさんのアラートを受け取りました。DBA に確認を依頼したところ、遅いクエ...

JS の原価と基準価額の問題に関する簡単な分析

プリミティブ値 -> プリミティブ型Number String Boolean undefin...

uniapp エントリーレベル nvue クライミングピット記録の分析

目次序文こんにちは世界画像 境界線の半径を設定する実ピクセルを設定する外部CSSをインポートttfフ...

Linuxのsortコマンドの複数のパラメータを理解するための1つの質問

sort コマンドは非常によく使用されますが、-o、-n、-u、-r などの多くのパラメーターがあり...

MySQL 8の新機能ウィンドウ関数の役割

MySQL 8.0 の新機能は次のとおりです。 Unicode 9.0 をすぐに完全にサポートウィン...

Centos7 の起動プロセスと Systemd での Nginx の起動構成

Centos7 の起動プロセス: 1.post(電源投入時のセルフテスト) 電源投入時のセルフテスト...

CSSスコープ(スタイル分割)の使用の概要

1. CSSスコープの使用(スタイル分割) Vue では、CSS スタイルを現在のコンポーネントでの...

Mysql 主キー UUID と自動増分主キーの違いと利点と欠点

導入私はしばらくの間、postgresql データベースを使用していました。クラウドに移行した後、自...

Vue+SpringBoot+Shiroのクロスドメイン問題を解決する

目次1. Vueフロントエンドを構成する1. クロスドメイン構成を開発する2. 本番環境のクロスドメ...