Chaining Ajax calls in AngularJs
Asked Answered
P

2

36

I would like to make multiple Ajax calls in a chain. But I also would like to massage the data after each call before making the next call. In the end, when All calls are successful, I would like to run some other code.

I am using Angular $http service for my Ajax calls and would like to stick to that.

Is it possible?

Plaything answered 29/4, 2013 at 17:11 Comment(0)
S
54

Yes, this is handled very elegantly by AngularJS since its $http service is built around the PromiseAPI. Basically, calls to $http methods return a promise and you can chain promises very easily by using the then method. Here is an example:

$http.get('http://host.com/first')
   .then(function(result){
    //post-process results and return
    return myPostProcess1(result.data); 
   })
   .then(function(resultOfPostProcessing){
    return $http.get('http://host.com/second'); 
   })
   .then(function(result){
    //post-process results of the second call and return
    return myPostProcess2(result.data); 
   })
   .then(function(result){
      //do something where the last call finished
   });

You could also combine post-processing and next $http function as well, it all depends on who is interested in the results.

$http.get('http://host.com/first')
   .then(function(result){
    //post-process results and return promise from the next call
    myPostProcess1(result.data); 
    return $http.get('http://host.com/second'); 
   })
   .then(function(secondCallResult){
     //do something where the second (and the last) call finished
   });
Sack answered 29/4, 2013 at 17:45 Comment(3)
Thanks Pawel, I will check it out. Right now, I used $q.all and seems to be doing what i want. But I will try this one too.Plaything
@Plaything q.all and the solution described here are 2 different things. q.all is great but works only for parallel requests, that is, if you don't care about their order and one requests doesn't depend on results of another. From your question I've understood that you are after chaining requests, where one requests needs to finish, you want to inspect / process results and only then issue another request.Sack
Turns out in my particular problem it was OK to run them in parallel but what I actually wanted was to run some code when all of them were done. However Your answer is still valuable because I am sure I will run into this sooner than later. I will accept your answer.Plaything
P
10

The accepted answer is good, but it doesn't explain the catch and finally methods which really put the icing on the cake. This great article on promises set me straight. Here's some sample code based on that article:

$scope.spinner.start();

$http.get('/whatever/123456')
  .then(function(response) {
     $scope.object1 = response.data;
     return $http.get('/something_else/?' + $scope.object1.property1);
  })
  .then(function(response) {
     $scope.object2 = response.data;
     if ($scope.object2.property88 == "a bad value")
        throw "Oh no! Something failed!";
     return $http.get('/a_third_thing/654321');
  })
  .then(function(response) {
     $scope.object3 = response.data;
  })
  .catch(function(error) {
     // this catches errors from the $http calls as well as from the explicit throw
     console.log("An error occured: " + error);
  })
  .finally(function() {
     $scope.spinner.stop();
  });
Persia answered 12/5, 2016 at 1:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.