Axiosは繰り返しのリクエストをキャンセル

Axiosは繰り返しのリクエストをキャンセル

序文

Web プロジェクトの開発プロセスでは、繰り返しリクエストが発生するシナリオに頻繁に遭遇します。システムが繰り返しリクエストを処理できない場合、システムでさまざまな問題が発生する可能性があります。たとえば、POST リクエストが繰り返されると、サーバー側で 2 つのレコードが生成される場合があります。では、重複したリクエストはどのように発生するのでしょうか?ここでは、2 つの一般的なシナリオを示します。

  • ページにボタンがあり、ユーザーがボタンをクリックすると、AJAX リクエストが開始されるとします。ボタンが制御されていない場合、ユーザーがボタンをすばやくクリックすると、繰り返しリクエストが行われます。
  • テスト結果クエリ ページで、ユーザーは「合格」、「不合格」、「すべて」の 3 つのクエリ条件に基づいてテスト結果をクエリできるとします。リクエストの応答が遅い場合、ユーザーがさまざまなクエリ条件をすばやく切り替えると、繰り返しのリクエストが生成されます。

重複リクエストがどのように生成されるかがわかったので、それが何らかの問題を引き起こす可能性があることもわかりました。次に、アバオ兄弟は Axios を例に、重複リクエストの問題を解決する方法を説明します。

1. リクエストをキャンセルする方法

Axios は、ブラウザと Node.js 環境の両方をサポートする Promise ベースの HTTP クライアントです。これは優れた HTTP クライアントであり、多数の Web プロジェクトで広く使用されています。ブラウザ環境では、Axios の基盤となるレイヤーは XMLHttpRequest オブジェクトを使用して HTTP リクエストを開始します。リクエストをキャンセルしたい場合は、XMLHttpRequest オブジェクトの abort メソッドを呼び出してリクエストをキャンセルできます。

xhr = new XMLHttpRequest();
xhr.open("GET", "https://developer.mozilla.org/", true);
xhr.send();
タイムアウトを設定します(() => xhr.abort(), 300);

Axios の場合、Axios が提供する CancelToken を通じてリクエストをキャンセルできます。

CancelToken は axios.CancelToken に置き換えられます。
const ソース = CancelToken.source();

axios.post('/user/12345', {
  名前: 'semlinker'
}, {
  キャンセルトークン: ソース.token
})

source.cancel('ユーザーによって操作がキャンセルされました。'); // キャンセル要求、パラメータはオプションです

さらに、次に示すように、CancelToken コンストラクターを呼び出して CancelToken を作成することもできます。

CancelToken は axios.CancelToken に置き換えられます。
キャンセルする;

axios.get('/user/12345', {
  キャンセルトークン: 新しいキャンセルトークン(関数executor(c) {
    キャンセル = c;
  })
});

cancel(); // リクエストをキャンセルする

CancelToken を使用して Axios でリクエストをキャンセルする方法がわかったので、CancelToken は内部でどのように動作するのでしょうか?まずこの質問を覚えておいてください。後で、アバオ兄弟がCancelTokenの秘密を明かします。次に、重複リクエストを判別する方法を分析しましょう。

2. 重複リクエストの判定方法

リクエストメソッド、リクエスト URL アドレス、リクエストパラメータが同じ場合、リクエストは同じであるとみなすことができます。したがって、リクエストが行われるたびに、現在のリクエストのリクエスト メソッド、リクエスト URL アドレス、リクエスト パラメータに基づいて一意のキーを生成し、リクエストごとに専用の CancelToken を作成し、キーとキャンセル関数をキーと値のペアとして Map オブジェクトに保存することができます。Map を使用する利点は、繰り返しのリクエストがあるかどうかをすばやく判断できることです。

'qs' から qs をインポートします

const pendingRequest = 新しい Map();
// GET -> パラメータ; POST -> データ
const requestKey = [メソッド、URL、qs.stringify(params)、qs.stringify(data)].join('&'); 
const cancelToken = new CancelToken(関数executor(cancel) {
  if(!pendingRequest.has(requestKey)){
    保留中のリクエストを設定します(リクエストキー、キャンセル)。
  }
})

重複したリクエストが発生した場合、キャンセル関数を使用して、以前に発行されたリクエストをキャンセルできます。リクエストをキャンセルした後、キャンセルされたリクエストを pendingRequest から削除する必要もあります。リクエストをキャンセルする方法と重複したリクエストを検出する方法がわかったので、重複したリクエストをキャンセルする方法を見てみましょう。

3. 繰り返しリクエストをキャンセルする方法

すべてのリクエストを処理する必要があるため、重複したリクエストをキャンセルする機能を実装するには、Axios のインターセプター メカニズムの使用を検討できます。 Axios は開発者にリクエスト インターセプターとレスポンス インターセプターを提供します。これらは次の機能を備えています。

  • リクエスト インターセプター: このタイプのインターセプターの機能は、リクエスト ヘッダーにトークン フィールドを追加するなど、リクエストが送信される前に特定の操作を均一に実行することです。
  • レスポンス インターセプター: このタイプのインターセプターの機能は、サーバー応答を受け取った後に特定の操作を一様に実行することです。たとえば、応答ステータス コードが 401 の場合、自動的にログイン ページにジャンプします。

3.1 補助機能の定義

リクエスト インターセプターとレスポンス インターセプターを構成する前に、次の 3 つの補助関数を定義しましょう。

generateReqKey: 現在のリクエスト情報に基づいてリクエスト キーを生成するために使用されます。
関数generateReqKey(config) {
  const { メソッド、URL、パラメーター、データ } = config;
  [メソッド、URL、Qs.stringify(params)、Qs.stringify(data)].join("&"); を返します。
}

addPendingRequest: 現在のリクエスト情報を pendingRequest オブジェクトに追加するために使用されます。

const pendingRequest = 新しい Map();
関数 addPendingRequest(config) {
  リクエストキーを生成するには、config を使用します。
  config.cancelToken = config.cancelToken || 新しい axios.CancelToken((キャンセル) => {
    保留中のリクエストにリクエストキーがある場合
       保留中のリクエストを設定します(リクエストキー、キャンセル)。
    }
  });
}

removePendingRequest: 重複したリクエストがあるかどうかを確認し、重複している場合は送信されたリクエストをキャンセルします。

関数removePendingRequest(config) {
  リクエストキーを生成するには、config を使用します。
  保留中のリクエストにリクエストキーがある場合
     リクエストキーをキャンセルします。
     リクエストキーをキャンセルします。
     保留中のリクエストを削除します(リクエストキー)。
  }
}

generateReqKey、addPendingRequest、および removePendingRequest 関数を作成したら、リクエスト インターセプターとレスポンス インターセプターを設定できます。

3.2 リクエストインターセプターの設定

axios.interceptors.request.use(
  関数(設定){
    removePendingRequest(config); // 重複したリクエストがあるかどうかを確認します。重複している場合は、送信したリクエストをキャンセルします。 addPendingRequest(config); // 現在のリクエスト情報を pendingRequest オブジェクトに追加します。 return config;
  },
  (エラー) => {
     Promise.reject(error) を返します。
  }
);

3.3 レスポンスインターセプターの設定

axios.interceptors.response.use(
  (応答) => {
     removePendingRequest(response.config); //pendingRequest オブジェクトからリクエストを削除します。 return response;
   },
   (エラー) => {
      removePendingRequest(error.config || {}); // pendingRequest オブジェクトからリクエストを削除します if (axios.isCancel(error)) {
        console.log("重複したリクエストをキャンセルしました: " + error.message);
      } それ以外 {
        // 例外処理を追加する }
      Promise.reject(error) を返します。
   }
);

完全なサンプルコードはかなり長いため、具体的なコードは掲載しません。ご興味がございましたら、以下のアドレスにアクセスしてサンプルコードを閲覧することができます。

完全なサンプルコード: https://gist.github.com/semlinker/e426780664f0186db434882f1e27ac3a

ここでは、Axios の重複リクエストのキャンセル例の結果を見てみましょう。

上図からわかるように、重複したリクエストが発生した場合、先に送信された未完了のリクエストはキャンセルされます。以下に、フローチャートを使用して重複リクエストをキャンセルするプロセスをまとめます。

最後に、上記の質問、つまり、CancelToken は内部でどのように機能するかに答えましょう。

4. キャンセルトークンの仕組み

前の例では、CancelToken コンストラクターを呼び出して CancelToken オブジェクトを作成しました。

新しい axios.CancelToken((キャンセル) => {
  保留中のリクエストにリクエストキーがある場合
    保留中のリクエストを設定します(リクエストキー、キャンセル)。
  }
})

次に、lib/cancel/CancelToken.js ファイルで定義されている CancelToken コンストラクターを分析します。

// lib/cancel/CancelToken.js
関数CancelToken(エグゼキュータ) {
  if (typeof executor !== 'function') {
    throw new TypeError('executor は関数である必要があります。');
  }

  var 解決Promise;
  this.promise = 新しいPromise(関数promiseExecutor(resolve) {
    解決の約束 = 解決します;
  });

  var トークン = this;
  executor(function cancel(message) { // キャンセルオブジェクトを設定する if (token.reason) {
      return; // キャンセルはすでにリクエストされています
    }
    token.reason = 新しいCancel(メッセージ);
    トークンを解決します。
  });
}

上記のコードから、cancel オブジェクトは関数であることがわかります。この関数を呼び出すと、Cancel オブジェクトが作成され、resolvePromise メソッドが呼び出されます。このメソッドが実行されると、CancelToken オブジェクトの promise プロパティによって指される promise オブジェクトの状態が解決されます。それで、これを行う目的は何でしょうか?ここで、lib/adapters/xhr.js ファイルから答えを見つけました。

// lib/アダプタ/xhr.js 
if (config.cancelToken) {
  config.cancelToken.promise.then(関数onCanceled(キャンセル) {
    if (!リクエスト) { return; }
    request.abort(); // リクエストをキャンセルするreject(cancel);
    リクエスト = null;
  });
}

上記の内容を読んだ後、CancelToken の動作原理を理解できない友人もいるかもしれません。そこで、Abao 兄弟は、CancelToken の動作原理をみんなに理解してもらうために、別の図を描きました。

V. 結論

この記事では、Axios で繰り返しリクエストをキャンセルする方法と、CancelToken の仕組みについて説明します。 以降の記事では、Abao Ge が Axios でデータ キャッシュを設定する方法を紹介します。 興味のある方は、ぜひお見逃しなく。 Axios での HTTP インターセプターと HTTP アダプターの設計と実装について学習したい場合は、「77.9K Axios プロジェクトから学ぶ価値のあることは何ですか」という記事をお読みください。

Axios による重複リクエストのキャンセルに関するこの記事はこれで終わりです。Axios による重複リクエストのキャンセルに関する詳細については、123WORDPRESS.COM の以前の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM を応援していただければ幸いです。

6. 参考資料

  • Github - アクシオス
  • MDN - XMLHttpRequest
  • 77.9K Axios プロジェクトから学ぶ価値のあることは何でしょうか?
以下もご興味があるかもしれません:
  • Axios グローバル リクエスト パラメータ設定、リクエストおよびリターン インターセプター メソッド
  • Vue が Axios リクエストとインターセプターをカプセル化する手順
  • Vue axios 繰り返しクリックで最後のリクエストをキャンセルするカプセル化メソッド
  • Axios で繰り返して無駄なリクエストをキャンセルする方法
  • Axios はリクエストをキャンセルし、重複リクエストを回避します
  • Vue axios インターセプターは、繰り返しリクエストのキャンセルによく使用されます。

<<:  Win10 に Linux ubuntu-18.04 デュアル システムをインストールする (インストール ガイド)

>>:  OracleデータをMySQLデータベースに抽出する実装プロセス

推薦する

Docker はキューとタスクのスケジューリングを実現するために Laravel アプリケーションをデプロイします

前回の記事では、Docker を使用して Laravel アプリケーションをデプロイする方法について...

MySQL データベースのアップグレードにおけるいくつかの「落とし穴」

商用データベースの場合、データベースのアップグレードは優先度が高く、バージョンアップのロードマップ、...

...

vue+echartsチャートの使用に関する問題記録

序文echarts は私が最もよく使用するチャート作成ツールであり、非常に完全なエコシステムとコンテ...

MySQL での mysqladmin 日常管理コマンドの概要 (必読)

mysqladmin ツールの使用形式は次のとおりです。 mysqladmin [オプション] コ...

MySQL マスタースレーブレプリケーションの原理と実践の詳細な説明

目次導入効果原理形状練習するこの記事では、例を使用して、MySQL マスター/スレーブ レプリケーシ...

Mysql 5.7.17 をインストールした後、MySQL にログインするチュートリアル

mysql-5.7.17 のインストールについては記事の下部で紹介されているので、参考にしてください...

MySQLデータベースは重複データを削除し、メソッドインスタンスを1つだけ保持します

1. 問題の紹介ユーザー テーブルに 3 つのフィールドが含まれているシナリオを想定します。 id、...

Vue3.0 でページング コンポーネントを手動でカプセル化する方法

この記事では、vue3.0の手動カプセル化ページングコンポーネントの具体的なコードを参考までに紹介し...

XHTML と CSS の Web ページ作成の問題に対する解決策

XHTML CSS ページ制作中に遭遇する問題の解決策は、解決策と呼ぶには少々大げさです。せいぜい、...

Linux centos7 に phpMyAdmin をインストールするチュートリアル

yum install httpd php mariadb-server –yランプの動作環境を設定...

選択ドロップダウンメニューのテキストを左右にスクロールするように設定する

marquee タグを使用してフォントのスクロールを設定したいです。コードは次のように記述しましたが...

MySQL5.7 シングルインスタンス自動起動サービスの設定プロセス

1.MySQLのバージョン [root@clq システム]# mysql -v MySQL モニター...

JavaScript データ型変換の例 (他の型を文字列、数値型、ブール型に変換する)

序文データ型変換とは何ですか?フォームまたはプロンプトを使用して取得されるデフォルトのデータ型は文字...

SQL 実装 LeetCode (185. 部門内で最も給与の高い上位 3 名)

[LeetCode] 185. 部門別給与上位3位従業員テーブルにはすべての従業員が保持されます。...