Gaurav Goenka
Gaurav Goenka

Reputation: 142

$http.post call inside another $http.post

I want to make an $http.post inside another $http.post as the second one is dependant on the first. Basically what I'm doing is:

$http.post("/my/server/location").then(function (response) {
    $http.post("/my/second/api/call/"+response.data.number).then(function (response) {
      $scope.message = "Created successfully";
    }, function (response){
      $scope.message = "Could not create";
    });

    //Create modal from response.data received from first API Call
    //Add $scope.message to this modal.
    });

What's happening as you would have guessed is the second one stays pending until the initial promise is returned, and I want to show $scope.message in the modal which is hence, not possible. While I understand why that's happening, I can't seem to figure how to get around that. I tried dealing with $q but made a mess out of it. Any help will be gladly appreciated.

Upvotes: 0

Views: 1413

Answers (4)

Cameron Rodriguez
Cameron Rodriguez

Reputation: 146

$http.post("/my/server/location")
 .then(function (response) {

    $http.post("/my/second/api/call/"+response.data.number).then(function 
      (response) {

     }, function (response){

     });

    $scope.message = "Created successfully";

     //Create modal from response.data received from first API Call
    //Add $scope.message to this modal.
    $scope.buildModal(response.data);

})
.catch(function(error){
    $scope.message = "Could not create";
    $scope.buildModal();
})

So the issue with what you had was that $scope.message = "Created successfully"; was locked in the nested api call. By taking it out of that you can build your modal immediately after the first api call. In the code above, nothing is waiting for the second api call to finish because nothing is in its .then block

I moved the modal building to a separate function buildModal because it has to be called both from the .then and the .catch block

Upvotes: 0

georgeawg
georgeawg

Reputation: 48968

To chain the message use a return statement in both the success handler and the rejection handler of the second XHR:

$http.post("/my/server/location").then(function (response1) {
    return $http.post("/my/second/api/call/"+response1.data.number)
      .then(function (response2) {
        $scope.message = "Created successfully";
        return $scope.message;
    }).catch(function (errorResponse2) {
        $scope.message = "Could not create";
        return $scope.message;
    }).then(function(message) {

        //Create modal from response1.data received from first API Call
        //Add `message` from the second XHR to this modal.

        return [response1.data, message];
    });
});

The return statement in the .catch rejection handler converts the rejected promise to a success which is handled by the next .then method in the chain.

The final promise returns an array which has both the data from the first XHR and the message from the second XHR.

Chaining Promises

Because calling the .then method of a promise returns a new derived promise, it is easily possible to create a chain of promises.

It is possible to create chains of any length and since a promise can be resolved with another promise (which will defer its resolution further), it is possible to pause/defer resolution of the promises at any point in the chain. This makes it possible to implement powerful APIs.

— AngularJS $q Service API Reference - Chaining Promises

Upvotes: 3

samnu pel
samnu pel

Reputation: 914

Try this

var fn = {
    test: function() {
        return $http.post("/my/server/location");
    }
};

fn.test().success(function(response) {
  $http.post("/my/second/api/call/"+response.data.number).then(function (response) {
      $scope.message = "Created successfully";
    }, function (response){
      $scope.message = "Could not create";
      }
});

    
    

Upvotes: -1

Ben
Ben

Reputation: 2706

You're right, $q won't help here unless you want both promises to be executed at once and then wait for both of their responses.

Here you want to execute one promise then the other, which according to your code looks fine. However, anything you want to do after the second promise has executed needs to be done in that .then() block.

Example:

$http.post("/my/server/location").then(function (response) {
    $http.post("/my/second/api/call/"+response.data.number).then(function (response) {
       $scope.message = "Created successfully";
       // Create modal from response.data received from first API Call
    }, function (error){
        $scope.message = "Could not create";
    });
});

Upvotes: 0

Related Questions