Skip to content

Instantly share code, notes, and snippets.

@mzabriskie
Created March 18, 2015 15:35
Show Gist options
  • Star 9 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mzabriskie/ec3a25dd45dfa0de92c2 to your computer and use it in GitHub Desktop.
Save mzabriskie/ec3a25dd45dfa0de92c2 to your computer and use it in GitHub Desktop.
axios abort request
/**
* The problem with using Promises for a request API is that Promises
* make it difficult to abort the request. Typically when using XHR
* some factory will wrap the actual XHR, but ultimately will return
* the XHR object.
*
* ```
* var request = performRequest('/user/12345');
* request.abort();
* ```
*
* Using Promises, the Promise is what's returned.
*
* ```
* var promise = performRequest('/user/12345');
* promise.then((response) => { console.log(response); });
* ```
*
* How then can the request be aborted?
*
* Working on axios (https://github.com/mzabriskie/axios),
* I get a lot of requests (no pun intended) for how to
* handle aborting a request once it's been made. This is
* a potential workaround for aborting a request when using
* XHR with Promises.
*/
// Setup request config and initiate the request
var config = {
method: 'get',
url: '/user/12345'
};
axios(config);
// Internally axios will add a requestID property to the
// request config. This is an auto incrementing integer
// that is unique to the request.
console.log(config); // {method: 'get', url: '/user/12345', requestID: 0}
// Now the request can be aborted by passing the requestID
// to axios.abort. Behind the scenes axios will have a
// collection of requests indexed by requestID. The request
// can then be aborted if it hasn't already been fulfilled.
// This is very similar to how setTimeout/clearTimeout works.
axios.abort(config.requestID);
@aaronshaf
Copy link

Seems like a good interim solution, albeit a sad one.

@nathanharper
Copy link

Yeah, mutating the config feels weird but I'd rather have that than nothing. It would satisfy my use case to to be able to set a callback in the config that gets passed the id/xhr object, but I'm not sure how much the synchronicity matters to others.

@jstcki
Copy link

jstcki commented Mar 19, 2015

Maybe instead of mutating the original config you could only allow aborting if requestID is set beforehand. This way, a user could also specify custom IDs for different requests and most importantly would not have to keep the original config around between requests. As an added benefit one could cancel requests preemptively before starting new ones.

E.g.

axios({
  requestId: 'user',
  method: 'get',
  url: '/user/12345'
});

// And then

axios.abort('user');

This could even be extended to support more useful cases: Subsequent requests with the same ID could also either auto-cancel a running previous request or return the same promise (so data doesn't get re-fetched).

axios({
  requestId: 'user',
  method: 'get',
  url: '/user/888'
});

 // This cancels the previous request
axios({
  requestId: 'user',
  cancelPreviousRequest: true,
  method: 'get',
  url: '/user/999'
});

// This returns the same promise like the previous request.
axios({
  requestId: 'user',
  method: 'get',
  url: '/user/999'
});

@nathanharper
Copy link

👍 herrstucki's solution, that's looking nice.

@mzabriskie
Copy link
Author

I like the direction you've taken with this herrstucki. axios can then just track the requests that need to be tracked.

@Ashot-KR
Copy link

Any plans to include this solution in release?

@paulwehner
Copy link

bumping. Yes please include this for a future release if it hasn't already.

@eisisig
Copy link

eisisig commented Jun 24, 2015

I like herrstucki idea. I would not use this often but when I would, I would like to have it clear and obvious what can and cannot be canceled

@pluma
Copy link

pluma commented Jun 30, 2015

What about just adding a cancel method to the promise it returns? Seems a lot more straightforward than keeping track of request IDs. Cancellable promises aren't entirely unheard of.

The promise should also be rejected with an error clearly indicating that the request was cancelled to allow checking this during error handling and not triggering the usual self-healing code one would trigger if the request failed due to a real error.

@mzabriskie
Copy link
Author

I disagree with aborting triggering an error @pluma. I think that it should do nothing.

axios({
  url: '/some/url',
  requestId: 'whatever'
}).then(function (res) {
  console.log('Request was successful');
}).catch(function (res) {
  console.log('An error occurred');
});

axios.abort('whatever');

In this case, nothing should be logged. It's not an error, so it shouldn't hit the catch. At the same time it's obviously not a successful request so it shouldn't enter then either. It should simply abort the request, as if it was never made.

@mik01aj
Copy link

mik01aj commented Aug 6, 2015

I agree with @pluma about adding the method to the returned promise. How about this API:

var request = axios({
  url: '/some/url',
});
request.then(function (res) {
  console.log('Request was successful');
}).catch(function (res) {
  console.log('An error occurred');
});

request.abort();

So, the API is one thing, and error handling is another.

@esnunes
Copy link

esnunes commented Jan 21, 2016

any news on this? I believe it should reject the promise with an Abort state. How would it work with es7 async await, e.g:

const { data } = await axios({
  url: '/some/url',
});

In case the promise doesn't get rejected the code about would stuck forever.

@rauchg
Copy link

rauchg commented Feb 7, 2016

Agreed with @esnunes. Aborting it is an error in the fulfillment of the promise's goal (which was to "return" the response data). Just because it's developer-initiated it doesn't mean it's not an error in the request flow.

@diessica
Copy link

diessica commented May 13, 2016

Agreed with @herrstucki's comment. cancelPreviousRequest would be pretty useful!

@chadwilken
Copy link

This doesn't seem to work on 0.15.3. Is there a way to do it now? I see there are cancellation tokens but I want to be able to prevent duplicate requests to the same URL from executing if one is still pending.

@Braunson
Copy link

Braunson commented Apr 28, 2017

@mzabriskie Any updates on this, interested to. abort() isn't an option in the latest, cancelPreviousRequest would be useful. I know the latest supports cancelTokens now but they don't work for me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment