Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RFC] API for canceling HTTP requests #333

Closed
nickuraltsev opened this issue May 24, 2016 · 24 comments
Closed

[RFC] API for canceling HTTP requests #333

nickuraltsev opened this issue May 24, 2016 · 24 comments
Assignees

Comments

@nickuraltsev
Copy link
Contributor

Overview

I would like to revive the discussion about canceling HTTP requests (#50) as there is clearly a demand for this feature. I suggest considering the following options. /cc @mzabriskie

Option 1

API

var axios = require('axios');

function generateRequestId() {
  // Return a unique request ID
}

var requestId = generateRequestId(); 
axios.get('/user', { requestId: requestId });
axios.abort(requestId);

Implementation

PR #330

Option 2

API

var axios = require('axios');
var Cancellation = axios.Cancellation;

var cancellation = new Cancellation();
axios.get('/user', { cancellation: cancellation });
cancellation.cancel();

Notes

  • When a request is canceled, the Promise is rejected with a CancellationError. This allows the caller to distinguish between a cancellation and a failure.
  • The same Cancellation object can be used to cancel multiple different requests.

Implementation

I created a separate library that can be used as a base for implementing request cancellation in axios: https://github.com/nickuraltsev/cancel. (The example on the README.md shows how to implement a simple HTTP client that supports cancellation.) We can copy all the code from this library to axios or add this library as a dependency.

@mzabriskie
Copy link
Member

Option 3

API

import axios from 'axios'

let cancelRequest
let promise = new Promise((resolve) => {
  cancelRequest = resolve
});

window.addEventListener('beforeunload', (e) => {
  cancelRequest()
})

axios.get('/user', {
  timeout: promise
})

Notes

  • If the Promise is resolved the request is canceled. This is what Angular does with $http service.

Implementation

The implementation for this is simply checking config.timeout instanceof Promise and if it is adding a then to it which if called cancels the request that is being made.

@msangui
Copy link
Contributor

msangui commented May 26, 2016

Abort on retry can be even more important than abort by itself. For example the most common use case for aborting XHR requests is when you are doing an autocomplete logic, we should discuss that feature as well.

@mzabriskie
Copy link
Member

I just saw that TC39 is discussing a proposal for Cancelable Promises

@nickuraltsev
Copy link
Contributor Author

@mzabriskie Yes, I'm aware of that proposal. It consists of two parts (slide 23):

  • Cancellation as a third state
  • Cancellation tokens

I don't think we can use cancelable promises in axios API before they are implemented in the browsers (I may be wrong). But I do think that we can use cancellation tokens to request cancellation. That is what Option 2 is about. I think we should align the cancellation token API to match the one described in the proposal though.

As for the third state, I would suggest to reject promises with a special error (e.g. CancellationError) for now. Once cancellable tokens are implemented, we can update axios to cancel the promise instead of rejecting it. This is not going to happen soon, so I don't think we should wait for it.

Thoughts?

@diessica
Copy link

diessica commented Jun 2, 2016

Option 1 seems good enough for me. Also liked @herrstucki's approach to the issue.

@pasin
Copy link

pasin commented Jun 7, 2016

Is there a timeline for the abort API to be finalized and implemented? IMO, it is a good idea to have the API inline with the Cancelable Promise spec.

@just-boris
Copy link

just-boris commented Jun 13, 2016

I think it is possible to implement any option as a custom adapter (based on XHR) and then try it in a real project.
Is there anybody who already tried that?

@aototo
Copy link

aototo commented Jun 15, 2016

I think Option 1 is good idea . @mzabriskie

@just-boris
Copy link

I tried to use Option 2 in my project and found it nice. If anybody else would like to try this out, I published this as project just-boris/axios-cancel. It is custom adapter which accepts cancellation object in options. See installation instructions in readme to get started

@beckiechoi
Copy link

beckiechoi commented Aug 3, 2016

I also second Option 2, it's more future proof. @nickuraltsev any ETA? In the meantime, I might just do what @just-boris did or deal with a fork...

@jeffijoe
Copy link

I like the idea of cancellation tokens as @just-boris is doing - this is also how it's done in .NET.

Basically make a cancellation token and pass it in, and when cancel() is called, abort the request and reject with a CancellationError.

@andrewmclagan
Copy link

Option 2 is really awesome...!

@just-boris
Copy link

I think that while promise calcellation spec is not finalized, this feature will not be implemented in core. To gracefully adopt cancellation feature, it would be better to use this as plugin, like I did.

If anybody interested, I can publish axios-cancel on NPM for convinience.

@nickuraltsev
Copy link
Contributor Author

I believe this feature should be implemented in core. There is no way to build it as a plugin without re-implementing axios adapters as it's done in axios-cancel which seems to be more a fork rather than a plugin.

Here is my suggestion:

  • Short-term plan:
  • Long-term plan:
    • Once cancellation is standardized and implemented in browsers/node, we can update axios to use built-in cancellation primitives. (It will be a breaking change so we will need to bump the version number appropriately.)

I think that the short-term solution doesn't need to be perfect. The goal is to make it possible to cancel requests and handle cancellations. Once it's in place, users will have a choice of using the axios API as is or build another API on top of it. Now, there are no options except re-implementing the adapter as @just-boris did.

@mzabriskie If you agree with this approach, I can create a PR. Please let me know what you think.

@mzabriskie
Copy link
Member

I don't think that creating offshoot adapter implementations is the correct approach. This will be difficult to maintain and keep synchronized with the core adapters. There will also need to be an offshoot maintained for both node's http as well as browser's xhr.

I agree with having a short-term and long-term plan. I support @nickuraltsev's proposal above.

@nickuraltsev
Copy link
Contributor Author

Great, I'll submit a PR soon.

@nickuraltsev nickuraltsev self-assigned this Aug 18, 2016
@miraage
Copy link

miraage commented Aug 25, 2016

@nickuraltsev what's current progress status?

@nhducit
Copy link

nhducit commented Aug 26, 2016

I vote for option 1 or option 2

@pavel06081991
Copy link

Any news?

@nickuraltsev
Copy link
Contributor Author

Just a heads up that I'm actively working on this feature. I'm hoping it will be ready in a couple of days.

@nickuraltsev
Copy link
Contributor Author

I've just submitted a PR

@wlingke
Copy link

wlingke commented Oct 1, 2016

Any news on when this will be released in an official version?

@nickuraltsev
Copy link
Contributor Author

Fixed via #452

@comerc
Copy link

comerc commented May 13, 2017

FYI: Promise Cancellation Is Dead — Long Live Promise Cancellation!

@axios axios locked and limited conversation to collaborators May 21, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests