Aborting AJAX Requests Using $http And AngularJS
In AngularJS, you use the $http service to make AJAX requests. When you initiate the AJAX request, you have to provide $http with a configuration object. One of the configuration options is "timeout". This option takes either a numeric value (milliseconds) or a promise. If the promise is resolved before the AJAX request has completed, AngularJS will call .abort() on the underlying XMLHttpRequest object.
NOTE: The timeout property only supports milliseconds and promises as of v1.2. Prior to that, the timeout option only supported milliseconds; meaning, there was no way to manually abort the underlying XMLHttpRequest object, even in v1.0.8.
As of late, I've been trying to create better encapsulation of the data persistence and retrieval mechanisms. This makes the matter a bit more complex because I don't want the calling context to have to worry about the $http service or about wiring up the timeout. To accomplish this, I have to create the deferred object and then inject it into the data response promise before I return it to the calling context. This way, the calling context can just call .abort() on the promise and the AJAX request will be aborted.
To see what I mean, take a look at the following code. The API in this demo (not shown) has a 5-second sleep() call to give us enough time to abort the request.
As you can see, after I've created the data-promise (as opposed to the AJAX-promise), I then augment it with an abort() method which will resolve the timeout.
The one big caveat to this approach is that if the calling context tries to invoke the .then() method on the resultant promise, the calling context will lose a handle on the .abort() method as it will be lost in the promise chain. This is why I am purposefully saving a reference to the primary promise before I hook into the resolution and rejection callbacks.
Aborting an AJAX request in AngularJS is not as easy as it is in jQuery. But, it's still possible; and, with enough encapsulation, you can still provide a simple interface for your data consumers. As a final note, I should also point out that $resource modules, as of v1.2, also provides a timeout option (though I have not yet tired it).
Want to use code from this post? Check out the license.
Hey, a co-worker pointed out that the timeout property accepts promises as of Angular 1.1.5
Ah, thanks for the clarification! I thought it was 1.2 because that was the first instance I found of it in the code. I'm still learning how to get around various branches in GitHub.
I've used this approach to add a .abort() method to the response object of my "httpi" AngularJS module:
very good keep it up.
I have used your approach with $resource, and tried both of these suggestions, but it is not working, the request doesn't get canceled.
here is the code
First off, I found your blog looking for some info about the $resource (Service? Factory? Provider? :P ) and found the rest of the posts so, so very good, that I already read a bunch of them.
But in this one, you lost me. I know it's because I certainly have no idea about how exactly promises work (Still trying to convince my mind that what the code does is *not* magic of the black kind).
Was wondering if you could point me to a good resource on the subject? (Promises, that is. For Angular I'd be subscribing to your blog!)
BTW, your post on "Using RESTful Controllers In An AngularJS Resource", if no exactly what I was looking for, is one of the *best* posts I've read on Angular. Thank you very much (You're not planning on writing a book, are you?)
Hi, I'm really new to AngularJS (coming from jQuery).
Your post was exactly what I searched for - thanks a lot! :)
The only thing on this solution I still got problems with is, that every time I cancel the request I got the error messages (Line 110-116).
Do you have a nice approach to distinguish between "cancel-errors" and "real" request errors (for ex. when server is not responding)?
I made a decorator over $http that does the same thing you have done over the service. Therefore canceling of $http promises is simple from the get go.
Thanks for your example as it helped immensely.
When I used HTTP get method, it works but it seems that it doesn't work on post method. But I will need to cancel post request, do you have any suggestions? You can take a look at my demonstration:
Hi , How do we cancel a particular request, when there are five request is in process.
For Example: If I am requesting 5 HTTP request, I want to cancel the third request , So how can I achieve this...
Very helpful!! Keep doing this great job! Thanks.
Tried to implement this to cancel all pending requests on route change. All Pending requests are getting canceled But, still success callback (provided in controller) executing and console displaying errors (response is undefined) when we change route while there are some requests in pending status. (Those requests got canceled).
If I am doing promise.reject("Route Rejection"); then it calls error callback but requests does not gets aborted.
Hi Ben, I have a web application with heavy server calls. By heavy, I mean that each request, take at least 15-20 seconds. User is permitted to switch between different menu items even when one is not loaded completely. For some impatient users, who can not wait for the loading bar to stop, the application becomes unresponsive after few clicks.
As a solution to this, I was thinking to cancel the request as soon as user switches from one menu item to another (on scope destroy). But this does not seem to work for me. The requests are aborted successfully. But still the next request takes the same amount of time if the first request was not aborted. Would you have any idea how to deal with this?
it seems that it doesn't work on post method.
how i can stop synchronize post in multiple ajax request?