0

I need to do two $http.post requests in my code. The first one retrieve a key that is used by the second one for looking up a SQL database.

At the moment, they're nested like this :

$http.post(...)
.success(function(data, status) {
    //Do something
    $http.post(...)
    .success(function(data, status) {
        //Do something else
    }
}

I highly doubt that this is the correct way of doing this. Can't I make the second request wait for the first one, and end up with something like :

$http.post(...)
.success(function(data, status) {
    //Do something
}

$http.post(...)
.success(function(data, status) {
    //Do something else
}
2
  • add if condition before call second request, after success first request call second request and use first request response data Commented May 26, 2016 at 7:39
  • Wellcome to callback hell :) The first snippet is the proper one. There are generators in EcmaScript 6 or async functions in EcmaScript 7 which are able to pause execution, so you can write async tasks in synchronous manner, but in ES5, the obvious and "best" way are callbacks. Commented May 26, 2016 at 7:48

4 Answers 4

3

One of the great advantages of using the promise API os that you can stop nesting your callbacks, this allows for far more readable/maintainable code.

$http.post(...)
.then(function(result) {
    // do something
    return $http.post(...);
})
.then(function(result) {
    // do something with the second result
});

You should also note that the success/error way of dealing with a promise has been deprecated

The $http legacy promise methods success and error have been deprecated. Use the standard then method instead. If $httpProvider.useLegacyPromiseExtensions is set to false then these methods will throw $http/legacy error.

https://docs.angularjs.org/api/ng/service/$http

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

1 Comment

There is a good tutorial on HTML5 rocks for dealing with promise chaining also checkout the angular docs for $q
0

The first one is the safest way, as the calls are asynchronous and you can't guarantee the order of execution. As an alternative you can choose to have a flag in success block of first call, based on which you can fire up the second post call..

1 Comment

flag won't help here, since $http passes control of it's execution to the next executable statement as soon as it call to server is made. It doesn't block execution till the time response from server arrives.
0

With angular is the only way that you can do that, there are not synchronous ajax in angular. also this kind of method is better to separate them in different methods.

Comments

0

$http is an asynchronous api. However you can make them to behave like a synchronous call by using $q service.

Here's an example demonstrating it.

Your first function

$scope.Func1= function () {
        var url= "http://stackoverflow.com";
        var query = "";
        var deferred = $q.defer();
        $http({
            url: url,
            method: "POST",
            data: query,
            headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
        })
        .then(function (response) {
            deferred.resolve(response.data);
        },
        function (response) {
            deferred.reject('failed');
        });
        return deferred.promise;
    };

Your second function

$scope.Func2= function (tmp) {
            var url= "http://stackoverflow.com";
            var query = "id="+tmp;
            $http({
                url: url,
                method: "POST",
                data: query,
                headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
            })
            .then(function (response) {
                // on success
            },
            function (response) {
                // on error
            });
        };

How to call them?

var promise = $scope.Func1();
    promise.then(function (resolve) {
        // this is called for deferred.resolve
        $scope.Func1(resolve); // calling second function
    },
    function (reject) {
        // this is called for deferred.reject
    });

3 Comments

In Func1 why not just return the promise generated by the $http call?
here's a great article (blog.ninja-squad.com/2015/05/28/angularjs-promises) explaining your question.
That article is no longer relevant $http now uses the $q interface - docs.angularjs.org/api/ng/service/$http

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.