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

推薦する

Vue マウスホイールスクロール切り替えルーティング効果を実装する方法

ルート ルーティング コンポーネント (アプリの下のルート ルーティング コンポーネント。子コンポー...

この記事では、イベント委任を使用してJavaScriptメッセージボード機能を実装する方法について説明します。

イベント委任を使用してメッセージ ボード機能を実装します。 <!DOCTYPE html>...

CentOS に MySQL 5.5 をインストールするための完全な手順

目次1. インストール前の準備、インストールパッケージのダウンロード1 インストールの準備2 インス...

Linuxファイル削除後にスペースが解放されない問題の詳しい説明

序文システム領域の使用量が大きすぎて消去する必要がある場合、または特定のファイルを消去する必要がある...

CSSリストのスライドにより、下部に隠れるのを防ぎ、長い画面モデルの処理に適応します。

1. モバイル端末がリストスライドを処理するとき、WeChat には下部にページに戻るボタンが組み...

プロジェクトのフロントエンドとバックエンドでの Echart チャートの使用に関する詳細な説明

目次序文1. プロジェクトアーキテクチャ2. Echart公式サイトにアクセスして自己分析を学ぶ2....

Linuxでプロセスが占有するポート番号を表示する

Linux システム管理者にとって、サービスがポートに正しくバインドされているか、またはポートをリッ...

シンプルなショッピングフォームを実装するJavaScript

この記事では、簡単なショッピングフォームを実装するためのJavaScriptの具体的なコードを参考ま...

Centos7 で NIS を構成する詳細な手順

目次原理ネットワーク環境の準備インストール前の準備NIS サーバー操作NIS クライアント操作原理N...

フローティングメニュー、上下スクロール効果を実現できます

コードはさらに合理化できますが、時間の制約があるため、まずはここで投稿して、自分で最適化してメニュー...

MySQLの外部ネットワークアクセス権を開く方法

以下のように表示されます。主に認証コマンドを実行します: 2つの方法1. 任意のホストがユーザー b...

nginxプロセスロックの実装の詳細な説明

目次1. nginxプロセスロックの役割2. エントリーレベルのロックの使用3. nginxプロセス...

フロントエンドインタビューに必要なホモロジーとクロスドメインの詳細な説明

序文ご存知のとおり、ブラウザの相同性戦略とクロスドメイン方式も、フロントエンド面接で頻繁に遭遇する問...

HTML 形式の JSON 出力の例 (テスト インターフェース)

JSON データを美しいインデント形式で表示するには、最も単純な JSON.stringify 関...

テキストエリアをレイアウトしたときにテキストが左下にあり、サイズを変更できない問題の解決策

2つの小さな問題ですが、長い間私を悩ませていました。最初の質問テキストエリアの左側のテキストは常にテ...