Maxime Picard
Maxime Picard

Reputation: 683

How to cancel pending requests in AngularJS?

I have an input field. When there is a keyup on this field, I send a request with AJAX and $http service of angular. My problem is when another keyup event is triggered, I need to cancel all pending requests. I have seen a lot of answers, but I have not found a solution.

I tried two things :

A service that I call

App.factory('findArticlesService', function($http, $q) {
   var self = this;
   self.canceller = null;

   return {
       getArticles: function(route, formData) {
           if (self.canceller) {
               self.canceler.resolve("Other request is pending");
           }

           var deferred = $q.defer();
           self.canceller = $q.defer();

           $http.post(route, angular.toJson(formData), {timeout: self.canceller.promise}).success(function(data) {
                deferred.resolve({data: data}); 
           });

           return deferred.promise;
       }
   };
});

App.controller('mainCtrl', ['$scope', '$http', '$q', 'findArticlesService', function($scope, $http, $q, findArticlesService) {
    var res = findArticlesService.getArticles(route, $scope.formData);
    console.log(res);
}]);

It doesn't work well.

And this :

var canceller = $q.defer();
canceller.resolve();

$http.post(route, angular.toJson($scope.formData), {timeout: canceller.promise}).then(function(data) {...});

This cancel all requests before they are sent.

Can you help me ?

Upvotes: 4

Views: 3355

Answers (1)

JackNova
JackNova

Reputation: 3931

Since you are registering a factory and not a service you don't have to use 'this', your function is not going to be treated/instanciated as a constructor, with new keyword.

you need a service that maintains a canceller on every initiated request and cancels the previous request if another is sent

App.factory('findArticlesService', function($http, $q) {
  var canceller;

   return {
       getArticles: function(route, formData) {
           if (canceller) {
               canceller.resolve("Other request is pending");
           }
           canceller = $q.defer();

           return $http.post(route, angular.toJson(formData), {timeout: canceller.promise});

       }
   };
});

You don't even need an intermediary canceler, can use the same previous request as canceler

App.factory('findArticlesService', function($http) {
  var canceler,
      getArticles = function (route, formData) {
        if (canceler) {
          canceler.resolve('aborted');
        }
        canceler = $http.post(route, angular.toJson(formData), {timeout: canceler.promise});
        return canceler;
      };

  return {
   getArticles: getArticles
 };
});

Upvotes: 2

Related Questions