[reactjs] how to cancel/abort ajax request in axios

I use axios for ajax requests and reactJS + flux for render UI. In my app there is third side timeline (reactJS component). Timeline can be managed by mouse's scroll. App sends ajax request for the actual data after any scroll event. Problem that processing of request at server can be more slow than next scroll event. In this case app can have several (2-3 usually) requests that already is deprecated because user scrolls further. it is a problem because every time at receiving of new data timeline begins redraw. (Because it's reactJS + flux) Because of this, the user sees the movement of the timeline back and forth several times. The easiest way to solve this problem, it just abort previous ajax request as in jQuery. For example:

    $(document).ready(
    var xhr;

    var fn = function(){
        if(xhr && xhr.readyState != 4){
            xhr.abort();
        }
        xhr = $.ajax({
            url: 'ajax/progress.ftl',
            success: function(data) {
                //do something
            }
        });
    };

    var interval = setInterval(fn, 500);
);

How to cancel/abort requests in axios?

This question is related to reactjs flux reactjs-flux es6-promise axios

The answer is


Using cp-axios wrapper you able to abort your requests with three diffent types of the cancellation API:

1. Promise cancallation API (CPromise):

Live browser example

 const cpAxios= require('cp-axios');
 const url= 'https://run.mocky.io/v3/753aa609-65ae-4109-8f83-9cfe365290f0?mocky-delay=5s';
 
 const chain = cpAxios(url)
      .timeout(5000)
      .then(response=> {
          console.log(`Done: ${JSON.stringify(response.data)}`)
      }, err => {
          console.warn(`Request failed: ${err}`)
      });
 
 setTimeout(() => {
    chain.cancel();
 }, 500);

2. Using AbortController signal API:

 const cpAxios= require('cp-axios');
 const CPromise= require('c-promise2');
 const url= 'https://run.mocky.io/v3/753aa609-65ae-4109-8f83-9cfe365290f0?mocky-delay=5s';
 
 const abortController = new CPromise.AbortController();
 const {signal} = abortController;
 
 const chain = cpAxios(url, {signal})
      .timeout(5000)
      .then(response=> {
          console.log(`Done: ${JSON.stringify(response.data)}`)
      }, err => {
          console.warn(`Request failed: ${err}`)
      });
 
 setTimeout(() => {
    abortController.abort();
 }, 500);

3. Using a plain axios cancelToken:

 const cpAxios= require('cp-axios');
 const url= 'https://run.mocky.io/v3/753aa609-65ae-4109-8f83-9cfe365290f0?mocky-delay=5s';

 const source = cpAxios.CancelToken.source();
 
 cpAxios(url, {cancelToken: source.token})
      .timeout(5000)
      .then(response=> {
          console.log(`Done: ${JSON.stringify(response.data)}`)
      }, err => {
          console.warn(`Request failed: ${err}`)
      });
 
 setTimeout(() => {
    source.cancel();
 }, 500);

There is really nice package with few examples of usage called axios-cancel. I've found it very helpful. Here is the link: https://www.npmjs.com/package/axios-cancel


https://github.com/axios/axios#cancellation

const CancelToken = axios.CancelToken;
                const source = CancelToken.source();
                let url = 'www.url.com'


                axios.get(url, {
                    progress: false,
                    cancelToken: source.token
                })
                    .then(resp => {

                        alert('done')

                    })

                setTimeout(() => {
                    source.cancel('Operation canceled by the user.');
                },'1000')

Typically you want to cancel the previous ajax request and ignore it's coming response, only when a new ajax request of that instance is started, for this purpose, do the following:

Example: getting some comments from API:

// declare an ajax request's cancelToken (globally)
let ajaxRequest = null; 

function getComments() {

    // cancel  previous ajax if exists
    if (ajaxRequest ) {
        ajaxRequest.cancel(); 
    }

    // creates a new token for upcomming ajax (overwrite the previous one)
    ajaxRequest = axios.CancelToken.source();  

    return axios.get('/api/get-comments', { cancelToken: ajaxRequest.token }).then((response) => {
        console.log(response.data)
    }).catch(function(err) {
        if (axios.isCancel(err)) {
           console.log('Previous request canceled, new request is send', err.message);
        } else {
               // handle error
        }
    });
}

import React, { Component } from "react";
import axios from "axios";

const CancelToken = axios.CancelToken;

let cancel;

class Abc extends Component {
  componentDidMount() {
    this.Api();
  }

  Api() {
      // Cancel previous request
    if (cancel !== undefined) {
      cancel();
    }
    axios.post(URL, reqBody, {
        cancelToken: new CancelToken(function executor(c) {
          cancel = c;
        }),
      })
      .then((response) => {
        //responce Body
      })
      .catch((error) => {
        if (axios.isCancel(error)) {
          console.log("post Request canceled");
        }
      });
  }

  render() {
    return <h2>cancel Axios Request</h2>;
  }
}

export default Abc;


Using useEffect hook:

useEffect(() => {
  const ourRequest = Axios.CancelToken.source() // <-- 1st step

  const fetchPost = async () => {
    try {
      const response = await Axios.get(`endpointURL`, {
        cancelToken: ourRequest.token, // <-- 2nd step
      })
      console.log(response.data)
      setPost(response.data)
      setIsLoading(false)
    } catch (err) {
      console.log('There was a problem or request was cancelled.')
    }
  }
  fetchPost()

  return () => {
    ourRequest.cancel() // <-- 3rd step
  }
}, [])

Note: For POST request, pass cancelToken as 3rd argument

Axios.post(`endpointURL`, {data}, {
 cancelToken: ourRequest.token, // 2nd step
})

This is how I did it using promises in node. Pollings stop after making the first request.

 var axios = require('axios');
    var CancelToken = axios.CancelToken;
    var cancel;
    axios.get('www.url.com',
                      {
                        cancelToken: new CancelToken(
                            function executor(c) {
                                cancel = c;
                             })
                      }
            ).then((response) =>{            
                cancel();               
              })

Examples related to reactjs

Error: Node Sass version 5.0.0 is incompatible with ^4.0.0 TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received type undefined raised when starting react app Template not provided using create-react-app How to resolve the error on 'react-native start' Element implicitly has an 'any' type because expression of type 'string' can't be used to index Invalid hook call. Hooks can only be called inside of the body of a function component How to style components using makeStyles and still have lifecycle methods in Material UI? React Hook "useState" is called in function "app" which is neither a React function component or a custom React Hook function How to fix missing dependency warning when using useEffect React Hook? Unable to load script.Make sure you are either running a Metro server or that your bundle 'index.android.bundle' is packaged correctly for release

Examples related to flux

how to cancel/abort ajax request in axios How to download fetch response in react as file Why use Redux over Facebook Flux? Pretty Printing JSON with React How to store Configuration file and read it using React

Examples related to reactjs-flux

How to toggle boolean state of react component? How to make a rest post call from ReactJS code? how to cancel/abort ajax request in axios Having services in React application How to download fetch response in react as file How to submit a form using Enter key in react.js? Why use Redux over Facebook Flux? Expected corresponding JSX closing tag for input Reactjs

Examples related to es6-promise

How to reject in async/await syntax? What is difference between Axios and Fetch? What is an unhandled promise rejection? JavaScript ES6 promise for loop Returning Promises from Vuex actions how to cancel/abort ajax request in axios Axios get access to response header fields How to pass parameter to a promise function Wait until all promises complete even if some rejected Handling errors in Promise.all

Examples related to axios

How to post query parameters with Axios? Has been blocked by CORS policy: Response to preflight request doesn’t pass access control check How can I add raw data body to an axios request? Axios Delete request with body and headers? Axios having CORS issue Axios handling errors Returning data from Axios API axios post request to send form data Change the default base url for axios Access Control Origin Header error using Axios in React Web throwing error in Chrome