Feature: Cancel $http request #1159

Closed
coli opened this Issue Jul 18, 2012 · 73 comments

Comments

Projects
None yet
@coli

coli commented Jul 18, 2012

Use case is we started a new $http request, and therefore needs to cancel 1 or more previous $http requests.

Eg:

var previousPromises = [];
previousPromises.push($http().then(function(){}));
...

Then:
//previousPromises[0].cancel()
or
//previousPromises[0].reject()

Reference
https://groups.google.com/forum/?fromgroups#!searchin/angular/cancel$20http/angular/aT-MowZoPJg/kPEr5Ja0GEwJ

@coli

This comment has been minimized.

Show comment Hide comment
@coli

coli Jul 18, 2012

A slightly related feature is ability to cancel a promise, or if the promise has a reference to the defer, then we can do promise.defered.reject();

coli commented Jul 18, 2012

A slightly related feature is ability to cancel a promise, or if the promise has a reference to the defer, then we can do promise.defered.reject();

@markwaddle

This comment has been minimized.

Show comment Hide comment
@markwaddle

markwaddle Sep 26, 2012

i need this feature as well.

i have an interface where a user can quickly trigger many actions that in turn trigger $http requests. in the case that a request is triggered and one is currently waiting for a response, i would like to be able to cancel it before requesting the new one.

i need this feature as well.

i have an interface where a user can quickly trigger many actions that in turn trigger $http requests. in the case that a request is triggered and one is currently waiting for a response, i would like to be able to cancel it before requesting the new one.

@koistya

This comment has been minimized.

Show comment Hide comment
@koistya

koistya Sep 30, 2012

Me too, need that feature.

koistya commented Sep 30, 2012

Me too, need that feature.

@markwaddle

This comment has been minimized.

Show comment Hide comment
@markwaddle

markwaddle Sep 30, 2012

An alternative to enabling request cancellation would be to allow the client to optionally pass in a key for the request and $http would ensure that only one request per key is pending at any point in time. The latest request with a specific key would always trump prior requests with that key. $http would need to cancel any pending requests with the same key before sending the new request. If the key was falsy it would send the request without consideration for pending requests. In other words, any number of requests with falsy keys could be pending simultaneously. The promises for the cancelled requests could be rejected.

This solution would suit my use case very well, and I suspect others' use cases too, and it might also be simpler to implement because you would not need to change the promise interface.

An alternative to enabling request cancellation would be to allow the client to optionally pass in a key for the request and $http would ensure that only one request per key is pending at any point in time. The latest request with a specific key would always trump prior requests with that key. $http would need to cancel any pending requests with the same key before sending the new request. If the key was falsy it would send the request without consideration for pending requests. In other words, any number of requests with falsy keys could be pending simultaneously. The promises for the cancelled requests could be rejected.

This solution would suit my use case very well, and I suspect others' use cases too, and it might also be simpler to implement because you would not need to change the promise interface.

@samunplugged

This comment has been minimized.

Show comment Hide comment
@samunplugged

samunplugged Oct 20, 2012

+1 for this feature.

+1 for this feature.

@jbeard4

This comment has been minimized.

Show comment Hide comment
@jbeard4

jbeard4 Oct 31, 2012

+1 from me as well

jbeard4 commented Oct 31, 2012

+1 from me as well

@gregwebs

This comment has been minimized.

Show comment Hide comment
@gregwebs

gregwebs Nov 13, 2012

+1

+1

@jinder

This comment has been minimized.

Show comment Hide comment
@jinder

jinder Nov 14, 2012

+1

jinder commented Nov 14, 2012

+1

@marknadig

This comment has been minimized.

Show comment Hide comment
@marknadig

marknadig Nov 20, 2012

Contributor

+1

Contributor

marknadig commented Nov 20, 2012

+1

@sssilver

This comment has been minimized.

Show comment Hide comment
@sssilver

sssilver Nov 30, 2012

+1

+1

@rick-kln

This comment has been minimized.

Show comment Hide comment
@rick-kln

rick-kln Dec 2, 2012

+1

rick-kln commented Dec 2, 2012

+1

@gonzaloruizdevilla

This comment has been minimized.

Show comment Hide comment
@gonzaloruizdevilla

gonzaloruizdevilla Dec 12, 2012

Contributor

@dbinit I think you should reject the promise when the abort method is called. The function that will handle the rejection can use the status parameter to find out if it was an abort request or different kind of error and then act consequently.

Contributor

gonzaloruizdevilla commented Dec 12, 2012

@dbinit I think you should reject the promise when the abort method is called. The function that will handle the rejection can use the status parameter to find out if it was an abort request or different kind of error and then act consequently.

@nicolacity

This comment has been minimized.

Show comment Hide comment
@nicolacity

nicolacity Dec 27, 2012

Need this feature! +1

Need this feature! +1

@amirnissim

This comment has been minimized.

Show comment Hide comment
@amirnissim

amirnissim Jan 2, 2013

+1

+1

@johnoscott

This comment has been minimized.

Show comment Hide comment
@johnoscott

johnoscott Jan 10, 2013

+1

+1

@georgiosd

This comment has been minimized.

Show comment Hide comment
@georgiosd

georgiosd Jan 14, 2013

+1

+1

@fredrikbonander

This comment has been minimized.

Show comment Hide comment
@fredrikbonander

fredrikbonander Jan 16, 2013

Contributor

+1

Contributor

fredrikbonander commented Jan 16, 2013

+1

@rick-kln

This comment has been minimized.

Show comment Hide comment
@rick-kln

rick-kln Jan 16, 2013

dbinit's solution worked perfectly for me.

dbinit's solution worked perfectly for me.

@ryankshaw

This comment has been minimized.

Show comment Hide comment
@ryankshaw

ryankshaw Jan 26, 2013

+1, @dbinit this new fix looks really nice!

+1, @dbinit this new fix looks really nice!

@ryankshaw

This comment has been minimized.

Show comment Hide comment
@ryankshaw

ryankshaw Jan 31, 2013

another thing that i need is to be able to bind to the progress event of the xhr upload.

for example (in plain javascript):

var xhr = new XMLHttpRequest();
xhr.upload.addEventListener("progress", uploadProgress, false)

I want to be able to do the same thing by doing $http.post...

so maybe rather than just adding an abort method, it would be good to provide something that lets me just get at the original xhr object.

another thing that i need is to be able to bind to the progress event of the xhr upload.

for example (in plain javascript):

var xhr = new XMLHttpRequest();
xhr.upload.addEventListener("progress", uploadProgress, false)

I want to be able to do the same thing by doing $http.post...

so maybe rather than just adding an abort method, it would be good to provide something that lets me just get at the original xhr object.

@markwaddle

This comment has been minimized.

Show comment Hide comment
@markwaddle

markwaddle Jan 31, 2013

@ryankshaw that sounds like a separate request deserving of its own issue

  • Mark

On Wed, Jan 30, 2013 at 4:07 PM, Ryan Shaw notifications@github.com wrote:

another thing that i need is to be able to bind to the progress event of
the xhr upload.

for example (in plain javascript):

var xhr = new XMLHttpRequest();
xhr.upload.addEventListener("progress", uploadProgress, false)

I want to be able to do the same thing by doing $http.post...

so maybe rather than just adding an abort method, it would be good to
provide something that lets me just get at the original xhr object.


Reply to this email directly or view it on GitHubhttps://github.com/angular/angular.js/issues/1159#issuecomment-12920190.

@ryankshaw that sounds like a separate request deserving of its own issue

  • Mark

On Wed, Jan 30, 2013 at 4:07 PM, Ryan Shaw notifications@github.com wrote:

another thing that i need is to be able to bind to the progress event of
the xhr upload.

for example (in plain javascript):

var xhr = new XMLHttpRequest();
xhr.upload.addEventListener("progress", uploadProgress, false)

I want to be able to do the same thing by doing $http.post...

so maybe rather than just adding an abort method, it would be good to
provide something that lets me just get at the original xhr object.


Reply to this email directly or view it on GitHubhttps://github.com/angular/angular.js/issues/1159#issuecomment-12920190.

@ryankshaw

This comment has been minimized.

Show comment Hide comment
@ryankshaw

ryankshaw Feb 1, 2013

@markwaddle, I just filed it as a separate issue in #1934

@markwaddle, I just filed it as a separate issue in #1934

@jorlow

This comment has been minimized.

Show comment Hide comment
@jorlow

jorlow Feb 21, 2013

+1

jorlow commented Feb 21, 2013

+1

@mping

This comment has been minimized.

Show comment Hide comment
@mping

mping Feb 28, 2013

+1

mping commented Feb 28, 2013

+1

@ybogdanov

This comment has been minimized.

Show comment Hide comment
@ybogdanov

ybogdanov Mar 7, 2013

+1

+1

dbinit added a commit to dbinit/angular.js that referenced this issue Mar 7, 2013

feat($http): promise.abort method
New $http specific method "abort" for promises. There are many cases
where a long-running request might need to be interrupted, e.g. a view
change.

Implementation details:
- after calling abort(), the promise is guaranteed to be resolved with a
  rejection (unless it has already been resolved)
- abort() returns true if successfully aborted (or already aborted), or
  false if the abort failed because the promise was already resolved
- has mock $httpBackend support

Closes #1159
@johnoscott

This comment has been minimized.

Show comment Hide comment
@johnoscott

johnoscott Mar 14, 2013

Looks like this issue is still open while we wait the PR #1836 by @dbinit to be merged. I really want to see this capability in the production code. What's the hold up ?

Looks like this issue is still open while we wait the PR #1836 by @dbinit to be merged. I really want to see this capability in the production code. What's the hold up ?

@MickeJagekrans

This comment has been minimized.

Show comment Hide comment
@MickeJagekrans

MickeJagekrans Mar 14, 2013

+1

@TomKaltz

This comment has been minimized.

Show comment Hide comment
@TomKaltz

TomKaltz Mar 14, 2013

+1
On Mar 14, 2013 8:24 AM, "MickeJagekrans" notifications@github.com wrote:

+1


Reply to this email directly or view it on GitHubhttps://github.com/angular/angular.js/issues/1159#issuecomment-14908361
.

+1
On Mar 14, 2013 8:24 AM, "MickeJagekrans" notifications@github.com wrote:

+1


Reply to this email directly or view it on GitHubhttps://github.com/angular/angular.js/issues/1159#issuecomment-14908361
.

@jasonkuhrt

This comment has been minimized.

Show comment Hide comment
@jasonkuhrt

jasonkuhrt Mar 22, 2013

We just got snagged by this in our production code too. Currently our work around is to disable UI since during pending requests if, say, the user triggers another request before a pending one returns, the app will break in unpredictable ways.

We just got snagged by this in our production code too. Currently our work around is to disable UI since during pending requests if, say, the user triggers another request before a pending one returns, the app will break in unpredictable ways.

@mping

This comment has been minimized.

Show comment Hide comment
@mping

mping Mar 22, 2013

WhAt I have done is to ensure requests are processed in the same order,
kinda like a Lamport timestamp.

On Friday, March 22, 2013, Jason Kuhrt wrote:

We just got snagged by this in our production code too. Currently our work
around is to disable UI since during pending requests because if, say, the
user triggers another request before a pending one returns, the app will
break in unpredictable ways.


Reply to this email directly or view it on GitHubhttps://github.com/angular/angular.js/issues/1159#issuecomment-15312838
.

mping commented Mar 22, 2013

WhAt I have done is to ensure requests are processed in the same order,
kinda like a Lamport timestamp.

On Friday, March 22, 2013, Jason Kuhrt wrote:

We just got snagged by this in our production code too. Currently our work
around is to disable UI since during pending requests because if, say, the
user triggers another request before a pending one returns, the app will
break in unpredictable ways.


Reply to this email directly or view it on GitHubhttps://github.com/angular/angular.js/issues/1159#issuecomment-15312838
.

@thisgeek

This comment has been minimized.

Show comment Hide comment
@thisgeek

thisgeek Mar 23, 2013

Man, I want this too, and access to an inner XHR object as proposed in #1934, but we can't cancel a promise, not directly. Promises are for observation only. You should never be able to abort a promise, resolve it, reject it, or affect it's state in any way. Any function that returns a promise needs a guarantee that no one who uses it can mess with it. For this same reason, promises should not provide access to the deferred from which it came.

If $http() (or some wrapper) could provide a new deferred, which can control state, then I think we'd be in business. The new deferred object would finish (1) once the http promise resolves or fails, or (2) once someone calls resolve() or reject() on that deferred, whichever comes first.

But a function need only return a deferred object if it should provide any and all consumers with the power to reject the same, original promise. I believe that it most cases we get want by creating a new, already rejected promise in a chain of then() calls, as suggested in the $q.reject() documentation.

Man, I want this too, and access to an inner XHR object as proposed in #1934, but we can't cancel a promise, not directly. Promises are for observation only. You should never be able to abort a promise, resolve it, reject it, or affect it's state in any way. Any function that returns a promise needs a guarantee that no one who uses it can mess with it. For this same reason, promises should not provide access to the deferred from which it came.

If $http() (or some wrapper) could provide a new deferred, which can control state, then I think we'd be in business. The new deferred object would finish (1) once the http promise resolves or fails, or (2) once someone calls resolve() or reject() on that deferred, whichever comes first.

But a function need only return a deferred object if it should provide any and all consumers with the power to reject the same, original promise. I believe that it most cases we get want by creating a new, already rejected promise in a chain of then() calls, as suggested in the $q.reject() documentation.

mbj referenced this issue Apr 4, 2013

chore($browser): remove the addJs method
this was never meant to be a public api used by apps. I refactored
the code to hide the functionality.

BREAKING CHANGE: $browser.addJs method was removed

apps that depended on this functionality should either use many of the
existing script loaders or create a simple helper method specific to the
app.
@elemoine

This comment has been minimized.

Show comment Hide comment
@elemoine

elemoine Apr 18, 2013

+1 Pretty important feature.

+1 Pretty important feature.

@IgorMinar IgorMinar closed this in 9f4f593 May 20, 2013

@praseodym praseodym referenced this issue in WISVCH/dienst2 May 27, 2013

Closed

Zoeken - Requests die door elkaar lopen #4

@saurabhnanda

This comment has been minimized.

Show comment Hide comment
@saurabhnanda

saurabhnanda Jun 6, 2013

Has this been added to any release yet? So, how does this work, exactly? While making a $http request you pass it an additional promise in the form of a timeout parameter. If the timeout promise resolve, the $http request will be canceled with the $http promise being rejected. Is that correct?

Has this been added to any release yet? So, how does this work, exactly? While making a $http request you pass it an additional promise in the form of a timeout parameter. If the timeout promise resolve, the $http request will be canceled with the $http promise being rejected. Is that correct?

@dbinit

This comment has been minimized.

Show comment Hide comment
@dbinit

dbinit Jun 6, 2013

Contributor

Yes, it's in the 1.1.5 release (changelog).

Here's the example I had above:

var canceler = $q.defer();
$http.get('/someUrl', {timeout: canceler.promise}).success(successCallback);
// later...
canceler.resolve();  // Aborts the $http request if it isn't finished.

Basically, you can use any promise as the timeout parameter. If it is resolved before the request completes, then the request will be aborted and the $http promise will be rejected.

Contributor

dbinit commented Jun 6, 2013

Yes, it's in the 1.1.5 release (changelog).

Here's the example I had above:

var canceler = $q.defer();
$http.get('/someUrl', {timeout: canceler.promise}).success(successCallback);
// later...
canceler.resolve();  // Aborts the $http request if it isn't finished.

Basically, you can use any promise as the timeout parameter. If it is resolved before the request completes, then the request will be aborted and the $http promise will be rejected.

@coli

This comment has been minimized.

Show comment Hide comment
@coli

coli Jun 6, 2013

Just curious, was adding a cancel method to promise explored?

coli commented Jun 6, 2013

Just curious, was adding a cancel method to promise explored?

@dbinit

This comment has been minimized.

Show comment Hide comment
@dbinit

dbinit Jun 6, 2013

Contributor

@coli, yes, I tried several different approaches (see PRs #1623, #1836, #2452, #2523). None of them were approved.

See also: #2529 (comment)

Contributor

dbinit commented Jun 6, 2013

@coli, yes, I tried several different approaches (see PRs #1623, #1836, #2452, #2523). None of them were approved.

See also: #2529 (comment)

@coli

This comment has been minimized.

Show comment Hide comment
@coli

coli Jun 6, 2013

Ah... thanks for the great work :)

promise.deferred.cancel() ? Hahaha.

coli commented Jun 6, 2013

Ah... thanks for the great work :)

promise.deferred.cancel() ? Hahaha.

@allyjunio

This comment has been minimized.

Show comment Hide comment
@allyjunio

allyjunio Jun 10, 2013

+1

+1

@fxck

This comment has been minimized.

Show comment Hide comment
@fxck

fxck Jul 2, 2013

Any reason this shouldn't work? Because it doesn't fire the request at all..

        el.bind('keyup', function() {

            var canceler = $q.defer();

            $http.post('/api', data, {timeout: canceler.promise}).success(function(returnData) {
            });
            canceler.resolve();
        });

fxck commented Jul 2, 2013

Any reason this shouldn't work? Because it doesn't fire the request at all..

        el.bind('keyup', function() {

            var canceler = $q.defer();

            $http.post('/api', data, {timeout: canceler.promise}).success(function(returnData) {
            });
            canceler.resolve();
        });
@dbinit

This comment has been minimized.

Show comment Hide comment
@dbinit

dbinit Jul 2, 2013

Contributor

You need to wrap your code with scope.$apply. Bind doesn't do it implicitly.

Contributor

dbinit commented Jul 2, 2013

You need to wrap your code with scope.$apply. Bind doesn't do it implicitly.

@fxck

This comment has been minimized.

Show comment Hide comment
@fxck

fxck Jul 2, 2013

$q needs it? Becuase $http doesn't.. anyway it' still not firing the request no matter if I put it inside scope.$apply(function(){}); or just put scope.$apply() after it..

fxck commented Jul 2, 2013

$q needs it? Becuase $http doesn't.. anyway it' still not firing the request no matter if I put it inside scope.$apply(function(){}); or just put scope.$apply() after it..

@dbinit

This comment has been minimized.

Show comment Hide comment
@dbinit

dbinit Jul 2, 2013

Contributor

Hmm, I think the $http.post doesn't fire the request until the next digest cycle. So the canceler.resolve is canceling it before it happens.

Try putting a scope.$apply between the $http.post and canceler.resolve.

Contributor

dbinit commented Jul 2, 2013

Hmm, I think the $http.post doesn't fire the request until the next digest cycle. So the canceler.resolve is canceling it before it happens.

Try putting a scope.$apply between the $http.post and canceler.resolve.

@gonzaloruizdevilla

This comment has been minimized.

Show comment Hide comment
@gonzaloruizdevilla

gonzaloruizdevilla Jul 2, 2013

Contributor

It seems to me like it is working.
You resolve the canceler promise immediately just after creating the request. You don't give any time to the request.

Contributor

gonzaloruizdevilla commented Jul 2, 2013

It seems to me like it is working.
You resolve the canceler promise immediately just after creating the request. You don't give any time to the request.

@knalli

This comment has been minimized.

Show comment Hide comment
@knalli

knalli Jul 2, 2013

Ehm, that's AngularJS. Every external event call must invoke the scope digester.

$http will create the request with the next scope cycle.. the example above have not one.

knalli commented Jul 2, 2013

Ehm, that's AngularJS. Every external event call must invoke the scope digester.

$http will create the request with the next scope cycle.. the example above have not one.

@fxck

This comment has been minimized.

Show comment Hide comment
@fxck

fxck Jul 2, 2013

@dbinit that works, thanks!

fxck commented Jul 2, 2013

@dbinit that works, thanks!

@elemoine

This comment has been minimized.

Show comment Hide comment
@elemoine

elemoine Jul 2, 2013

See #2442 for the issue reporting on $http requiring to be called within a $watch. That really sounds like a bug to me, as one should be able to call $http from any context.

elemoine commented Jul 2, 2013

See #2442 for the issue reporting on $http requiring to be called within a $watch. That really sounds like a bug to me, as one should be able to call $http from any context.

@e-oz

This comment has been minimized.

Show comment Hide comment
@e-oz

e-oz Jul 18, 2013

great thing. thank you very much!

e-oz commented Jul 18, 2013

great thing. thank you very much!

@markstickley

This comment has been minimized.

Show comment Hide comment
@markstickley

markstickley Oct 3, 2013

Seems like I'm about 4 months too late but doesn't the approach of hijacking the timeout parameter means that you can't have both a fixed timeout AND the option to manually cancel (due to the request being made obsolete) without rolling your own timeout functionality? That seems rather limited. Do we know if separating this joint functionality into discrete parts is on the roadmap at all?

Seems like I'm about 4 months too late but doesn't the approach of hijacking the timeout parameter means that you can't have both a fixed timeout AND the option to manually cancel (due to the request being made obsolete) without rolling your own timeout functionality? That seems rather limited. Do we know if separating this joint functionality into discrete parts is on the roadmap at all?

@coli

This comment has been minimized.

Show comment Hide comment
@coli

coli Oct 3, 2013

@markstickley It's just a promise you control, it has nothing to do with timeout

coli commented Oct 3, 2013

@markstickley It's just a promise you control, it has nothing to do with timeout

@dbinit

This comment has been minimized.

Show comment Hide comment
@dbinit

dbinit Oct 3, 2013

Contributor

@markstickley You can just use the promise returned by $timeout and then do $timeout.cancel(promise) if you want to cancel the request early.

Contributor

dbinit commented Oct 3, 2013

@markstickley You can just use the promise returned by $timeout and then do $timeout.cancel(promise) if you want to cancel the request early.

@markstickley

This comment has been minimized.

Show comment Hide comment
@markstickley

markstickley Oct 3, 2013

@dbinit That's a decent workaround, thanks I'll try that :)

@dbinit That's a decent workaround, thanks I'll try that :)

@btford

This comment has been minimized.

Show comment Hide comment
@btford

btford Oct 4, 2013

Contributor

I wrote a service demonstrating how one might encapsulate this functionality here: http://plnkr.co/edit/P8wKns51GVqw5mwS5l5R?p=preview

I thought it might be useful for anyone that comes across this thread in the future.

Contributor

btford commented Oct 4, 2013

I wrote a service demonstrating how one might encapsulate this functionality here: http://plnkr.co/edit/P8wKns51GVqw5mwS5l5R?p=preview

I thought it might be useful for anyone that comes across this thread in the future.

@derekrprice

This comment has been minimized.

Show comment Hide comment
@derekrprice

derekrprice Nov 7, 2013

btford's plunker isn't completely working for me. The cancelQuery = null in $http.post().success() backfires. success() gets called asynchronously for cancelled requests, so with a query launched on keypress, if I type quickly some of the cancelQuery info is lost, meaning only some requests are cancelled. If I just remove the cancelQuery = null line, everything works fine.

btford's plunker isn't completely working for me. The cancelQuery = null in $http.post().success() backfires. success() gets called asynchronously for cancelled requests, so with a query launched on keypress, if I type quickly some of the cancelQuery info is lost, meaning only some requests are cancelled. If I just remove the cancelQuery = null line, everything works fine.

@phantomwhale

This comment has been minimized.

Show comment Hide comment
@phantomwhale

phantomwhale Nov 13, 2013

I ended up bringing in a boolean flag, so that I could differentiate between a "normal" error, and a manually cancelled error. The need to do this does seem to highlight this is indeed a "workaround" and perhaps could do with some better direct support at a later stage.

I modified @btford 's plunk to demonstrate this: http://plnkr.co/edit/BW6Zwu?p=preview

I ended up bringing in a boolean flag, so that I could differentiate between a "normal" error, and a manually cancelled error. The need to do this does seem to highlight this is indeed a "workaround" and perhaps could do with some better direct support at a later stage.

I modified @btford 's plunk to demonstrate this: http://plnkr.co/edit/BW6Zwu?p=preview

basarat added a commit to DefinitelyTyped/DefinitelyTyped that referenced this issue Nov 18, 2013

@fxck

This comment has been minimized.

Show comment Hide comment
@fxck

fxck Nov 19, 2013

has this stopped working for anyone in 1.2.1?

fxck commented Nov 19, 2013

has this stopped working for anyone in 1.2.1?

@anton000

This comment has been minimized.

Show comment Hide comment
@anton000

anton000 Feb 19, 2014

instead of relying on timeout, ended up wrapping $http in another deferred, then rejected that deferred when a new call was made or when i needed to "cancel". this had the result of still completing the $http call, but rejecting the data returned.

thoughts?

$scope.fetchData = function() {
  if ($scope.async) {
    $scope.async.reject();
  }
  $scope.async = testAsync();
  $scope.async.promise.then(
    function(data){
    console.log('success' + data);
    },
    function(data) {
      console.log('reject' + data);
    }
  );
}

testAsync = function() {
  var deferred = $q.defer();
  $http.get('/api/')
    .success(function(data) {
      deferred.resolve(data);
    })
    .error(function(data) {
      deferred.reject(data);
    });
  return deferred;
};

instead of relying on timeout, ended up wrapping $http in another deferred, then rejected that deferred when a new call was made or when i needed to "cancel". this had the result of still completing the $http call, but rejecting the data returned.

thoughts?

$scope.fetchData = function() {
  if ($scope.async) {
    $scope.async.reject();
  }
  $scope.async = testAsync();
  $scope.async.promise.then(
    function(data){
    console.log('success' + data);
    },
    function(data) {
      console.log('reject' + data);
    }
  );
}

testAsync = function() {
  var deferred = $q.defer();
  $http.get('/api/')
    .success(function(data) {
      deferred.resolve(data);
    })
    .error(function(data) {
      deferred.reject(data);
    });
  return deferred;
};
@snjoetw

This comment has been minimized.

Show comment Hide comment
@snjoetw

snjoetw Mar 28, 2014

@anton000 your code only rejects the wrapper promise. it doesn't actually cancel original $http promise

snjoetw commented Mar 28, 2014

@anton000 your code only rejects the wrapper promise. it doesn't actually cancel original $http promise

@anton000

This comment has been minimized.

Show comment Hide comment
@anton000

anton000 Mar 29, 2014

@snjoetw i explained in my post it still completes the original $http promise but rejects the data returned. I think using this matches the concept of promise to resolver communication being unidirectional as @IgorMinar explained in #2452 .

@snjoetw i explained in my post it still completes the original $http promise but rejects the data returned. I think using this matches the concept of promise to resolver communication being unidirectional as @IgorMinar explained in #2452 .

@anton000

This comment has been minimized.

Show comment Hide comment
@anton000

anton000 Jul 8, 2014

@mato75 This would be better asked on the blog itself which you got the snippet from, or over on sites like http://www.stackoverflow.com

anton000 commented Jul 8, 2014

@mato75 This would be better asked on the blog itself which you got the snippet from, or over on sites like http://www.stackoverflow.com

@BiosSun

This comment has been minimized.

Show comment Hide comment
@BiosSun

BiosSun Dec 4, 2014

+1

BiosSun commented Dec 4, 2014

+1

@codeniac

This comment has been minimized.

Show comment Hide comment
@codeniac

codeniac Apr 1, 2015

How is going this feature? I need it a lot!!! 👍

codeniac commented Apr 1, 2015

How is going this feature? I need it a lot!!! 👍

@e-oz

This comment has been minimized.

Show comment Hide comment
@e-oz

e-oz Apr 1, 2015

@ghost

This comment has been minimized.

Show comment Hide comment
@ghost

ghost Apr 17, 2015

couldn't you use config.timeout = $q.when('canceled') to cancel an $http request before it's actually sent?

ghost commented Apr 17, 2015

couldn't you use config.timeout = $q.when('canceled') to cancel an $http request before it's actually sent?

This was referenced Mar 13, 2017

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