axios でリクエストをキャンセルし、重複リクエストを防ぐ方法について簡単に説明します。

axios でリクエストをキャンセルし、重複リクエストを防ぐ方法について簡単に説明します。

序文

実際のプロジェクトでは、リクエストに対して「手ぶれ防止」処理を実行する必要がある場合があります。これは主に、特定の状況下でユーザーが短時間にボタンを繰り返しクリックして、フロントエンドがバックエンドに複数のリクエストを繰り返し送信するのを防ぐためです。ここでは、よくある 2 つの実際的な状況を挙げます。

  • PC側 - 検索ボタンをダブルクリックすると、2つの検索要求がトリガーされる可能性があります
  • モバイル端末 - モバイル端末ではクリック遅延がないため、誤操作や多重操作が発生しやすく、リクエストの再送信が発生します。

読み込みマスクがある場合でも上記の状況が発生する可能性があるため、フロントエンドで重複したリクエストを防ぐ方法を検討する必要があります。

コア - キャンセルトークン

Axios でリクエストをキャンセルする中心的な方法は CanelToken です。公式ウェブサイトのドキュメントには、CancelTokenを使用する方法が2つ記載されています。ここでは、簡単な貼り付けとコメントの追加方法を紹介します。

方法1:

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

axios.get('/user/12345', {
  //リクエストにはCancelTokenを設定する必要があります cancelToken: source.token
}).catch(関数(スロー) {
  // リクエストがキャンセルされた場合は、このメソッドに入り、(axios.isCancel(thrown)) かどうかを判断します。
    console.log('リクエストがキャンセルされました', throwed.message);
  } それ以外 {
    // エラーを処理する
  }
});

// 上記のリクエストをキャンセルします // source.cancel('messge') message はオプションであり、文字列である必要があります
source.cancel('ユーザーによって操作がキャンセルされました。');

方法2:

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

axios.get('/user/12345', {
  // オプションで直接 cancelToken オブジェクトを作成します cancelToken: new CancelToken(function executor(c) {
    キャンセル = c;
  })
});

// 上記のリクエストをキャンセルします cancel();

実用的なアプリケーションとパッケージング

上記では axios のコアメソッドを例示しましたが、実際には公式ウェブサイトの例のようにこれらを使用することはほとんどありません。代わりに、axios インターセプターでグローバル構成管理を行います。この場合、上記のコードにいくつか変更を加える必要があります。

私が実装した一般的なアイデアは次のとおりです。

  • 進行中のすべてのリクエストをキャッシュする必要があります。リクエストを開始する前に、キャッシュ リスト内でリクエストが進行中かどうかを確認します。進行中の場合は、リクエストをキャンセルします。
  • リクエストが完了したら、リクエストを再送信できるようにキャッシュリストからリクエストを削除する必要があります。

アイデアが完成したら、すぐにコードに取り掛かりましょう

// 進行中のリクエストのリスト let reqList = []

/**
 * 重複リクエストを防止* @param {array} reqList - リクエストキャッシュリスト* @param {string} url - 現在のリクエストアドレス* @param {function} cancel - リクエスト中断関数* @param {string} errorMessage - リクエストが中断されたときに表示されるエラーメッセージ*/
const stopRepeatRequest = 関数 (reqList、url、cancel、errorMessage) {
  const errorMsg = エラーメッセージ || ''
  (i = 0 とします; i < reqList.length; i++) {
    if (reqList[i] === url) {
      キャンセル(エラーメッセージ)
      戻る
    }
  }
  reqList.push(url)
}

/**
 * リクエストの続行を許可する * @param {array} reqList すべてのリクエストのリスト * @param {string} url リクエストアドレス */
const allowRequest = 関数 (reqList, url) {
  (i = 0 とします; i < reqList.length; i++) {
    if (reqList[i] === url) {
      要求リスト.splice(i, 1)
      壊す
    }
  }
}

const サービス = axios.create()

// リクエストインターセプター service.interceptors.request.use(
  設定 => {
 キャンセルする
   // cancelToken オブジェクトを設定する config.cancelToken = new axios.CancelToken(function(c) {
     キャンセル = c
    })
    // 重複したリクエストを防ぎます。前のリクエストが完了していない場合、同じリクエストは停止されませんRepeatRequest(reqList, config.url, cancel, `${config.url} request is interrupted`)
    設定を返す
  },
  エラー => Promise.reject(エラー)
)

// レスポンスインターセプター service.interceptors.response.use(
  レスポンス => {
    // 遅延を増やします。同じリクエストが短期間に繰り返し送信されないようにする必要があります。setTimeout(() => {
      allowRequest(reqList、response.config.url) は、
    }, 1000)
    // ...リクエストが成功した後の後続の操作 // successHandler(response)
  },
  エラー => {
    もし(axios.isCancel(スロー)){
      console.log(スローされたメッセージ);
    } それ以外 {
      // 遅延を増やします。同じリクエストが短期間に繰り返し送信されないようにする必要があります。setTimeout(() => {
        allowRequest(reqList、error.config.url) は、
      }, 1000)
    }
    // ...リクエストが失敗した後の後続の操作 // errorHandler(error)
  }
)

いくつかの小さな詳細

上記の方法 2 のコードを使用して cancelToken を設定しなかったのはなぜですか?
axios のドキュメントには次のような注記があります:

注: 同じキャンセル トークンを使用して複数のリクエストをキャンセルできます。
同じトークンを使用して複数のリクエストをキャンセルできます。

したがって、各リクエストの前に新しいオブジェクトを作成したくありません。各キャンセルが正しく実行されるようにするには、必ず方法 2 を使用してください。前のメソッドでは、キャンセルが発生した後も後続のリクエストは引き続きキャンセルされます。

なぜ応答に遅延を追加する必要があるのでしょうか?
ユーザーが非常に短い期間内に同じリクエストを繰り返し行うことを望まないためです。
応答でリクエストをブロックすることと、リクエストでリクエストをブロックすることは、2 つの異なる概念であることに注意してください。
この要求は、前の要求が完了していない場合に同じ要求が再度開始されるのを防ぐためのものです。
この応答により、前のリクエストが完了してから一定期間内に同じリクエストが行われなくなります。

キャンセル時にメッセージだけでなくオブジェクトを渡すことはできますか?
公式インターフェースでは不可能です。公式ソースコードに従って再パッケージ化するか、サードパーティのプラグインを使用するか、別の方法(オブジェクトを JSON 文字列に変換し、必要に応じて再度変換する)を使用できます。

これで、axios でリクエストをキャンセルして重複リクエストを防ぐ方法についての記事は終了です。axios でリクエストをキャンセルして重複リクエストを防ぐ方法の詳細については、123WORDPRESS.COM の以前の記事を検索するか、次の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • Vue の Axios でリクエストをキャンセルし、重複リクエストを防ぐ方法

<<:  Zabbix で監視項目と集約されたグラフを設定するためのサンプルコード

>>:  mysql update文の実行プロセスの詳細な説明

推薦する

将来最も成功する企業はテクノロジー企業でしょうか、それともデザイン企業でしょうか?

ムーアの法則はもはや適用されない2004年にフレックストロニクスがフロッグデザインを買収したのを皮切...

JavaScript offsetParent のケーススタディ

1. offsetParentの定義: offsetParentは子要素に最も近い位置に配置された親...

CSS3 すりガラス効果

すりガラス効果がうまく表現されていれば、ページが非常に鮮やかで立体的に見えるようになります。写真に直...

同じレベルの要素で Position:fixed と margin-top を一緒に使用する場合の CSS の問題

問題の説明CSS を使用して上部の固定効果を実現したいと思います。 margin-top と pos...

ウェブページ読み込み時に左右にジャンプする原因の分析と解決

最近、ウェブサイトを設計するときにこの問題に遭遇しています。メンバーセンターを設計し、コンテンツを ...

MySQLのLIMIT文について詳しく説明します

目次質問サーバー層とストレージエンジン層LIMITって何ですか?何をするか?トゥカオ最近、Q&...

Navicat がデータベース データ構造をインポートする際に発生するエラー datetime(0) の SQL レポートの問題を解決します。

エラー発生: MySQL 5.7 から SQL にデータベースをエクスポートし、それを MySQL ...

SQL GROUP BYの詳細な説明と簡単な例

GROUP BY ステートメントは、Aggregate 関数と組み合わせて使用​​され、1 つ以上の...

ボタントリガーイベントを使用して背景色の点滅効果を実現します

背景色の点滅効果を実現するには、次のコードを <body> 領域に追加するだけです。コー...

CSS で高さが不明な垂直中央揃えを実装する

この記事では主に、高さが不明な垂直方向の中央揃えを CSS で実装する方法を紹介し、皆さんと共有しま...

値の転送を実現するために、2つの同じレベルのコンポーネントをVueで作成します。

Vue コンポーネントは接続されているため、コンポーネント間で値を渡す必要があるのは避けられません...

XAML でボタンを円として再描画する方法

XAML レイアウトを使用する場合、インターフェイスを Metro 風にするために、一部のボタンでは...

HTMLを圧縮しない理由はいくつかある

理由は簡単です。 HTML ドキュメントでは、複数の空白文字は 1 つの空白文字と同等です。つまり、...

ウェブページデザインのための4つの実践的なヒント

関連記事: Web コンテンツ ページを作成するための 9 つの実用的なヒント<br />...

Zen Coding 簡単で素早いHTMLの書き方

禅コーディングテキストエディタプラグインです。 Zen Coding を使用するテキスト エディター...