How to cancel an $http request in AngularJS?
This feature was added to the 1.1.5 release via a timeout parameter:
var canceler = $q.defer();$http.get('/someUrl', {timeout: canceler.promise}).success(successCallback);// later...canceler.resolve(); // Aborts the $http request if it isn't finished.
Cancelling Angular $http Ajax with the timeout property doesn't work in Angular 1.3.15. For those that cannot wait for this to be fixed I'm sharing a jQuery Ajax solution wrapped in Angular.
The solution involves two services:
- HttpService (a wrapper around the jQuery Ajax function);
- PendingRequestsService (tracks the pending/open Ajax requests)
Here goes the PendingRequestsService service:
(function (angular) { 'use strict'; var app = angular.module('app'); app.service('PendingRequestsService', ["$log", function ($log) { var $this = this; var pending = []; $this.add = function (request) { pending.push(request); }; $this.remove = function (request) { pending = _.filter(pending, function (p) { return p.url !== request; }); }; $this.cancelAll = function () { angular.forEach(pending, function (p) { p.xhr.abort(); p.deferred.reject(); }); pending.length = 0; }; }]);})(window.angular);
The HttpService service:
(function (angular) { 'use strict'; var app = angular.module('app'); app.service('HttpService', ['$http', '$q', "$log", 'PendingRequestsService', function ($http, $q, $log, pendingRequests) { this.post = function (url, params) { var deferred = $q.defer(); var xhr = $.ASI.callMethod({ url: url, data: params, error: function() { $log.log("ajax error"); } }); pendingRequests.add({ url: url, xhr: xhr, deferred: deferred }); xhr.done(function (data, textStatus, jqXhr) { deferred.resolve(data); }) .fail(function (jqXhr, textStatus, errorThrown) { deferred.reject(errorThrown); }).always(function (dataOrjqXhr, textStatus, jqXhrErrorThrown) { //Once a request has failed or succeeded, remove it from the pending list pendingRequests.remove(url); }); return deferred.promise; } }]); })(window.angular);
Later in your service when you are loading data you would use the HttpService instead of $http:
(function (angular) { angular.module('app').service('dataService', ["HttpService", function (httpService) { this.getResources = function (params) { return httpService.post('/serverMethod', { param: params }); }; }]);})(window.angular);
Later in your code you would like to load the data:
(function (angular) {var app = angular.module('app');app.controller('YourController', ["DataService", "PendingRequestsService", function (httpService, pendingRequestsService) { dataService .getResources(params) .then(function (data) { // do stuff }); ... // later that day cancel requests pendingRequestsService.cancelAll();}]);})(window.angular);
Cancelation of requests issued with $http
is not supported with the current version of AngularJS. There is a pull request opened to add this capability but this PR wasn't reviewed yet so it is not clear if its going to make it into AngularJS core.