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

推薦する

シンプルなID生成戦略: MySQLテーブルからグローバルに一意のIDを生成する実装

グローバル ID を生成する方法は多数あります。ここでは簡単な解決策を紹介します。MySQL の自動...

HTMLコードテキストボックスの制限入力テキストボックスが灰色になり、制限テキストボックスの入力

方法 1: readonly 属性を true に設定します。入力値=読み取り専用 readOnly...

効率的な視覚化Nginxログ表示ツール

目次導入インストール表示フィールドフィルターソートキー導入Rhit は、標準フォルダー (gzip ...

MySQL データベース開発の 36 の原則 (要約)

序文これらの原則は実際の戦闘から要約されています。あらゆる原則の背後には血なまぐさい教訓があるこれら...

JavaScript ドキュメント オブジェクト モデル DOM

目次1. JavaScriptはページ内のすべてのHTML要素を変更できる1. IDでHTML要素を...

サーバー間のファイル バックアップ ソリューション、サーバー ファイルを別のサーバーに自動的にバックアップする方法は?

多くの組織ではファイル サーバーをバックアップする必要があり、あるサーバーから別のファイル サーバー...

Unicode 署名 BOM の詳細な説明

Unicode 署名 BOM - BOM とは何ですか? BOM は Byte Order Mark...

ウェブサイトのコードブロックのpreタグにコピーコードボタンコードを追加します

他のよりプロフェッショナルなブログ システムを参照すると、コード ブロックにコードのコピー ボタンが...

Javascript サンプル プロジェクトでの虫眼鏡効果の実装プロセス

目次序文事例: JD.com の虫眼鏡効果の模倣オフセットシリーズクライアントシリーズスクロールシリ...

ウェブページを作るときに知っておくべきいくつかのスキル

1. IE6 では z-index が無効です。 CSS では、階層を変更するために z-index...

HTMLでは、div内のコンテンツが次のサイズを超えたときに自動的にスクロールバーが表示されるように設定します。

HTML ページでは、div 内のコンテンツが制限を超えた後に自動的にスクロール バーを表示する必要...

MySQL公式エクスポートツールmysqlpumpの使用

目次導入説明書実際の経験長所と短所総括する導入mysqlpump は mysqldump の派生です...

HTMLテキストの一般的なイベントとメソッドの詳細な説明

イベントの説明onactivate: オブジェクトがアクティブ要素として設定されたときに発生します。...

Docker を使用して Nginx+Flask+Mongo アプリケーションをデプロイする

サーバーにはNginx、データベースサポートにはMongo、Python言語のWebフレームワークに...

MySQL コピーテーブルと許可分析の 3 つの実装方法

テーブルを素早くコピーする方法まず、テーブル db1.t を作成し、1000 行のデータを挿入します...