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データベースに抽出する実装プロセス

推薦する

Mysql はテーブル内の古いデータを定期的にクリアし、いくつかのデータを保持します (推奨)

以下の目標を達成するため: Mysql データベースは、一定の間隔 (2 時間または 1 日、カスタ...

CSS で実現される HTML 背景色のグラデーション

エフェクトのスクリーンショット:実装コード:コードをコピーコードは次のとおりです。 <!DOC...

Docker実行コンテナが作成状態にある問題についての簡単な説明

最近の問題としては、次のような現象があります。システムには、docker run コマンドを継続的に...

MySQLスローログに関する知識のまとめ

目次1. スローログの紹介2. スローログの練習1. スローログの紹介スロー ログの正式名称はスロー...

React-Native スクリーンショットコンポーネント react-native-view-shot の紹介と使い方のまとめ

目次1. 現象2. 解決策3. 要約: 1. 現象1. 要件: 特定の表示ページをキャプチャしてアル...

clearfixとclearの例

この記事では、CSS を理解し始めたばかりの人を対象に、主に HTML で clearfix と c...

MySQLデータベースの使用仕様の概要

導入: MySQL データベースの仕様に関しては、皆さんも何らかのドキュメントを読んだことがあると思...

ReactのuseEffectクロージャの落とし穴についての簡単な説明

問題コードuseEffectによって発生したクロージャの問題コードを見てみましょう 定数 btn =...

WeChatアプレットで画像の幅と高さを取得する方法

起源最近、私は要件 A に取り組んでいます。そこには、次のように記述される小さな機能ポイントがありま...

MySQL ツリー構造データベース テーブル設計

目次序文1. 基本データ2. 継承駆動設計3. 左右の値のエンコーディングに基づく設計4. ツリー構...

JavaScriptでマクロを使用する方法

言語では、DSL を実装するためにマクロがよく使用されます。マクロを使用すると、開発者は JSX 構...

Linuxのバージョン情報を復号化する方法

Linux バージョンに関する情報を表示および解釈するのは、見た目よりも少し複雑です。単純なバージョ...

JavaScript クロージャの説明

目次1. クロージャとは何ですか? 2. クロージャの役割2.1) メモリ2.2) プライベート変数...

Ubuntu 18.04 でソースコードから Odoo14 をインストールするチュートリアル

目次このシリーズの背景概要PostgreSQL データベースの準備ソースからインストール仮想環境の作...

Ubuntu 20.04の新バージョンでルートユーザーを使用してシステムにログインする方法の詳細なチュートリアル

Ubuntu 20.04 では、デフォルトで root ログインが有効になっていないため、デスクトッ...