How to cancel an $http request in AngularJS?

Tags: AngularJs, $http, Cancel AngularJs Ajax

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 and cancel a request:

(function (angular) {

var app = angular.module('app');

app.controller('YourController', ["DataService", "PendingRequestsService", function (httpService, pendingRequestsService) {

    // cancel all running requests
    pendingRequestsService.cancelAll();

    // load new data
    dataService
    .getResources(params)
    .then(function (data) {    
    // do stuff    
    });    

    ...

    // later that day cancel requests    
    pendingRequestsService.cancelAll();
}]);

})(window.angular);

Sources:

http://odetocode.com/blogs/scott/archive/2014/04/24/canceling-http-requests-in-angularjs.aspx

http://www.bennadel.com/blog/2616-aborting-ajax-requests-using-http-and-angularjs.htm

http://stackoverflow.com/questions/13928057/how-to-cancel-an-http-request-in-angularjs/29399084#29399084

No Comments

Add a Comment