A brief discussion on how to cancel requests and prevent duplicate requests in axios

A brief discussion on how to cancel requests and prevent duplicate requests in axios

Preface

In actual projects, we may need to perform "anti-shake" processing on requests. This is mainly to prevent users from repeatedly clicking a button in a short period of time in certain circumstances, causing the front end to repeatedly send multiple requests to the back end. Here I list two common practical situations:

  • PC side - double-clicking the search button may trigger two search requests
  • Mobile terminal - Because there is no click delay on the mobile terminal, it is very easy to cause misoperation or multiple operations, resulting in request resending

The above situation may still occur when there is a loading mask, so we need to consider how to prevent duplicate requests on the front end.

Core - CancelToken

The core method of canceling a request in Axios is CanelToken. There are two ways to use CancelToken in the official website documentation. Here is a simple paste and add comments

Method 1:

const CancelToken = axios.CancelToken;
const source = CancelToken.source();

axios.get('/user/12345', {
  //CancelToken must be set for the request cancelToken: source.token
}).catch(function (thrown) {
  // If the request is canceled, enter this method to judge if (axios.isCancel(thrown)) {
    console.log('Request canceled', thrown.message);
  } else {
    // handle error
  }
});

// Cancel the above request // source.cancel('messge') message is optional and must be a String
source.cancel('Operation canceled by the user.');

Method 2:

const CancelToken = axios.CancelToken;
let cancel;

axios.get('/user/12345', {
  // Create a cancelToken object directly in options cancelToken: new CancelToken(function executor(c) {
    cancel = c;
  })
});

// Cancel the above request cancel();

Practical applications and packaging

The core methods in axios have been exemplified above, but in practice we often do not use them as in the official website examples. Instead, we do global configuration management in the axios interceptor. In this case we need to make some changes to the above code.

Here is the general idea I implemented:

  • We need to cache all ongoing requests. Before initiating a request, determine whether the request is in progress in the cache list. If so, cancel the request.
  • After any request is completed, the request needs to be deleted from the cache list so that the request can be resent

After the idea is finished, let's go directly to the code

// List of ongoing requests let reqList = []

/**
 * Prevent duplicate requests* @param {array} reqList - request cache list* @param {string} url - current request address* @param {function} cancel - request interrupt function* @param {string} errorMessage - error message to be displayed when request is interrupted*/
const stopRepeatRequest = function (reqList, url, cancel, errorMessage) {
  const errorMsg = errorMessage || ''
  for (let i = 0; i < reqList.length; i++) {
    if (reqList[i] === url) {
      cancel(errorMsg)
      return
    }
  }
  reqList.push(url)
}

/**
 * Allow a request to proceed * @param {array} reqList list of all requests * @param {string} url request address */
const allowRequest = function (reqList, url) {
  for (let i = 0; i < reqList.length; i++) {
    if (reqList[i] === url) {
      reqList.splice(i, 1)
      break
    }
  }
}

const service = axios.create()

// Request interceptor service.interceptors.request.use(
  config => {
 let cancel
   // Set the cancelToken object config.cancelToken = new axios.CancelToken(function(c) {
     cancel = c
    })
    // Prevent duplicate requests. When the previous request is not completed, the same request will not be stoppedRepeatRequest(reqList, config.url, cancel, `${config.url} request is interrupted`)
    return config
  },
  err => Promise.reject(err)
)

// Response interceptor service.interceptors.response.use(
  response => {
    // Increase the delay, the same request should not be sent repeatedly in a short period of time setTimeout(() => {
      allowRequest(reqList, response.config.url)
    }, 1000)
    // ...subsequent operations after the request is successful // successHandler(response)
  },
  error => {
    if (axios.isCancel(thrown)) {
      console.log(thrown.message);
    } else {
      // Increase the delay, the same request should not be sent repeatedly in a short period of time setTimeout(() => {
        allowRequest(reqList, error.config.url)
      }, 1000)
    }
    // ...subsequent operations after the request fails // errorHandler(error)
  }
)

Some small details

Why didn't you use the code in method 2 above to set cancelToken?
There is a note in the axios documentation:

Note: you can cancel several requests with the same cancel token.
You can cancel multiple requests using the same token.

So I don't want to create a new object before each request. Please be sure to use method 2 to ensure that each cancel is executed correctly. The previous method will cause subsequent requests to continue to be canceled after a cancellation occurs.

Why do we need to add delay to the response?
Because we don't want users to make the same request repeatedly in a very short period of time.
Please note that blocking requests in a response and blocking requests in a request are two different concepts:
The request is to prevent the same request from being started again when the previous request is not completed.
The response prevents the same request from being made within a certain period of time after the previous request is completed.

Can I pass an object when cancelling, instead of just a message?
It is not possible according to the official interface. You can repackage it according to the official source code, or use a third-party plug-in, or use another method: convert the object to a JSON string, and then convert it back where needed.

This is the end of this article about how to cancel requests and prevent duplicate requests in axios. For more information about how to cancel requests and prevent duplicate requests in axios, please search for previous articles on 123WORDPRESS.COM or continue to browse the following related articles. I hope you will support 123WORDPRESS.COM in the future!

You may also be interested in:
  • How to cancel requests and prevent duplicate requests in Axios in Vue

<<:  MySQL msi installation tutorial under windows10 with pictures and text

>>:  Detailed explanation of the execution process of mysql update statement

Recommend

How to encapsulate WangEditor rich text component in Angular

The rich text component is a very commonly used c...

How to change password in MySQL 5.7.18

How to change the password in MySQL 5.7.18: 1. Fi...

Version numbers in css and js links in HTML (refresh cache)

background Search the keyword .htaccess cache in ...

Vue parent component calls child component function implementation

Vue parent component calls the function of the ch...

Why Seconds_Behind_Master is still 0 when MySQL synchronization delay occurs

Table of contents Problem Description Principle A...

MySQL Billions of Data Import, Export and Migration Notes

I have been taking a lot of MySQL notes recently,...

Use pure CSS to achieve scroll shadow effect

To get straight to the point, there is a very com...

JS Object constructor Object.freeze

Table of contents Overview Example 1) Freeze Obje...

Summary of Linux commands commonly used in work

Use more open source tools such as docker and kub...

js to achieve simulated shopping mall case

Friends who are learning HTML, CSS and JS front-e...

SMS verification code login function based on antd pro (process analysis)

Table of contents summary Overall process front e...

HTML table border control implementation code

Generally, when we use a table, we always give it...

Vue realizes click flip effect

Use vue to simply implement a click flip effect f...