78

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?

Rajab Shakirov
  • 4,477
  • 6
  • 22
  • 40
  • 2
    Possible duplicate of [reactJS how to stop it listening to ajax request](http://stackoverflow.com/questions/37771305/reactjs-how-to-stop-it-listening-to-ajax-request) – elreeda Jul 12 '16 at 12:45
  • Your link helped to me solve this problem, but I'm still wondering how to cancel a request, instead stop listening to it... – Rajab Shakirov Jul 13 '16 at 12:31

8 Answers8

101

Axios does not support canceling requests at the moment. Please see this issue for details.

UPDATE: Cancellation support was added in axios v0.15.

EDIT: The axios cancel token API is based on the withdrawn cancelable promises proposal.

Example:

const cancelTokenSource = axios.CancelToken.source();

axios.get('/user/12345', {
  cancelToken: cancelTokenSource.token
});

// Cancel request
cancelTokenSource.cancel();
Sølve Tornøe
  • 3,038
  • 15
  • 27
Nick Uraltsev
  • 16,975
  • 4
  • 22
  • 14
  • 1
    @RajabShakirov Updated – Nick Uraltsev Oct 11 '16 at 15:56
  • 31
    Please include a minimal example in case the linked resource goes down! – totymedli Feb 22 '18 at 16:25
  • 2
    if you do this, it cant run anymore again – ichimaru Aug 21 '18 at 09:56
  • 3
    `const cancelTokenSource = axios.CancelToken.source(); axios.get('/user/12345', { cancelToken: cancelTokenSource.token }); cancelTokenSource.cancel();` – John Lee May 21 '19 at 21:06
  • Directly from the link: *"The axios cancel token API is based on the withdrawn cancelable promises proposal."* If I understand it correctly, it is based on something that is not supported, and in that case I don't want to use it. Apparently we have the still experimental [abortable fetch](https://developer.mozilla.org/en-US/docs/Web/API/AbortController) (see especially the example); I am curious how this evolves. See also [Can I use AbortController?](https://caniuse.com/#feat=abortcontroller) – Ali Oct 31 '19 at 22:24
  • Please implement te solution on StackOverflow instead of using External links – ecarrizo Nov 21 '19 at 14:24
  • Note that, when running `axios.post` it should be in the 3rd argument! Like this: `axios.post('/user/12345', {}, { cancelToken: cancelTokenSource.token });` – Arno van Oordt Oct 30 '20 at 13:04
  • Cancellation seems to trigger an error though, see @Vijay sadhu answer below for a catching example when cancellation is a normal expected behaviour. – Eric Burel Dec 01 '20 at 07:55
  • @ali based as insipired by or based as in implemented with? – zardilior Dec 16 '20 at 23:44
  • @zardilior If my interpretation is correct: implemented with. – Ali Dec 17 '20 at 08:23
  • @Ali thanks for clarifying that it is not certain that it is implemented with it. Sounded weird coming from a widely used library to be made on shaking grounds, specially as many apps are using it. Would be a real problem if your interpretation resulted in being true. – zardilior Dec 23 '20 at 20:41
23
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;

Naveen DA
  • 3,007
  • 3
  • 32
  • 42
Vijay sadhu
  • 464
  • 3
  • 10
  • You should *never* use a module scoped variable within a component. If you have two of them rendered, each one will wipe out the value set by the previous one. – erich2k8 Mar 06 '21 at 20:47
21

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
        }
    });
}
Ahmad Mobaraki
  • 4,078
  • 3
  • 35
  • 54
  • Nice solution. If anyone is using `axios.create` to create an instance, `cancelToken` and `isCancel` will not be available. You need to add them. https://github.com/axios/axios/issues/1330#issuecomment-378961682 – Kalimah Apr 24 '21 at 14:22
18

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
})
ErezSo
  • 13
  • 2
  • 2
anoNewb
  • 2,198
  • 16
  • 16
7

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

Kornel
  • 3,555
  • 3
  • 23
  • 29
5

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();               
              })
Legolas
  • 337
  • 6
  • 19
5

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')
mohammad nazari
  • 723
  • 7
  • 10
3

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);
  • 1
    I would not recommend this method because if you just cancel the promise, how are you certain that the actual request is stopped and not continuing in the background? It's better to stop the axios request within axios with the way it is built. Also, I just think this way is unnecessarily complex. – Zac Nov 05 '20 at 17:44
  • No, cp-axios is an axios wrapper that returns a cancellable promise which supports cancellation of internal tasks, in other words, cancellation of the returned promise will result in aborting of the related network request. It's not just a silent promise cancellation. Just check out the live demo posted above to see how the related network request is actually aborting when you abort the promise (see the network tab in your console). – Dmitriy Mozgovoy Nov 05 '20 at 18:11