0

I have a service making two consecutive calls to an API asynchronously.

I would like the app to wait for both to be resolved before proceeding and since one of calls may or may not be made, I believe $watch is the way to go versus nested or chained callbacks.

    var response_complete = {call1:false, call2:false};

    $http.post("myapi.com/slug", data, header).then(function(res){ 

        /* ... */

        response_complete.call1 = true;

    }); 

    if(make_this_call==true){

        $http.post("myapi.com/anotherslug", data, header).then(function(res){ 

            /*...*/

            response_complete.call2 = true;

        }); 

    } else response_complete.call2 = true;

    $scope.$watch("response_complete",function(){

        if(response_complete.call1==true && response_complete.call2==true){

            console.log("DONE!");
        }

    });

So the idea is to create a global variable, and watch it as the two calls complete. The second call, which is conditional, immediately sets it's response variable to true if it is not being made.

But the $watch callback is only fired once and the condition within it (call1 & call2 == true) is never met.

2
  • 1
    are you using angular 1? if angular one you can use broadcast for this Commented Sep 4, 2017 at 0:30
  • If you want both to be resolved, the easiest way is just to put the second call inside the first then. The sample provided by you wouldn't work because response_complete.call1 = true is inside an async thread and it is always false by the time you try to verify it. Commented Sep 4, 2017 at 0:37

2 Answers 2

1

your watch do not work as response complete is not a $scope variable | property:

 // replace this with $scope property declaration
 //var response_complete = {call1:false, call2:false};
 $scope.response_complete = {call1:false, call2:false};

then in your succeeding code use $scope.response_complete to modify its value and so your $watch will be triggered as $scope.response_complete changed.

A better solution:

As others have specified it is better to use $broadcast than $watch, so instead watching the variable throw events instead and catch those event inside your $scope.

$http.post("myapi.com/slug", data, header).then(function() {
    // stuff
    $scope.$broadcast("POST_SLUG_COMPLETE");
});

$http.post("myapi.com/anotherslug", data, header).then(function() {
    // stuff
    $scope.$broadcast("POST_ANOTHERSLUG_COMPLETE");
});

// then in your $scope

$scope.$on("POST_SLUG_COMPLETE", function () {
    // stuff
});

$scope.$on("POST_ANOTHERSLUG_COMPLETE", function () {
    // stuff
});

hope that helps

Sign up to request clarification or add additional context in comments.

2 Comments

I think the normal and simpler way is to just chain one then with the next request (see my answer), that's what async call were designer for. Maybe I missed or missunderstood something. If this works, is very good
It does work but the problem is you need to wait for the 1st request to finish before sending the next request which at least doubles the time it takes to finish unlike calling them separately both will be independent requests which are sent at the same time.
0

If you need your "global" variable for the current scope, you can just do:

$scope.complete = false; 
$http.post("myapi.com/slug", data, header).then(function(res) { 
    $http.post("myapi.com/anotherslug", data, header).then(function(res) { 
        $scope.complete = true;
        console.log("DONE!");
    });
});

You may also use $rootScope for a more "global" value. Other alternatives are $broadcast or a property inside a service.

But more important is to ensure how are you using the async calls. If you want both to be resolved put the second call inside the first. The sample provided by you wouldn't work because response_complete.call1 = true is inside an async thread and it is always false by the time you try to verify it

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.