20

How to make blocking http request in AngularJS so that i can use the $http response on very next line?

In the following example, $http object doesn't return the result to the next line so that I can pass this result to fullcalender(), a JavaScript library, because $scope.data returns blank value.

This is the sample code:

$http.get('URL').success(function(data){
    $scope.data = data;
});

$.fullCalender({
    data: $scope.data
});
4
  • Is there any way to avoid this? Javascript is single threaded, and making a synchronous HTTP request will block the ENTIRE BROWSER while it waits for a response. This should not be your preferred solution. Commented Nov 5, 2014 at 6:16
  • 1
    Could you not simply move the call to fullCalendar into the success callback and set data equal to the data arg of the callback? Commented Nov 5, 2014 at 6:17
  • when i use fullcalendar data in callback it is not displaying on template. Commented Nov 5, 2014 at 6:24
  • 2
    The reason why calendar doesn't trigger is because it is executed not in angular $digest loop. You have to place $.fullCalendar.... inside success callback and call $scope.$apply() after that Commented Jul 15, 2015 at 21:55

3 Answers 3

2

You can use promises for that.

here is an example:

$scope.myXhr = function(){

    var deferred = $q.defer();

    $http({
        url: 'ajax.php',
        method: 'POST',
        data:postData,
        headers: {'Content-Type': 'application/x-www-form-urlencoded'}
        })
        //if request is successful
        .success(function(data,status,headers,config){

            //resolve the promise
            deferred.resolve('request successful');

        })
        //if request is not successful
        .error(function(data,status,headers,config){
            //reject the promise
            deferred.reject('ERROR');
        });

    //return the promise
    return deferred.promise;
}

$scope.callXhrAsynchronous = function(){

    var myPromise = $scope.myXhr();

    // wait until the promise return resolve or eject
    //"then" has 2 functions (resolveFunction, rejectFunction)
    myPromise.then(function(resolve){
        alert(resolve);
        }, function(reject){
        alert(reject)      
    });

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

4 Comments

What's the reason to not return the promise that is created by $http? IT's a bad practice to wrap existing promises in deferreds
Because the promise thats created by $http is async
I wonder why this has been accepted as an answer. The OP asked about synchronous, and you answered asynchronous
@KingJulian is right, this is not an answer. $promise mangaes async calls in the "then" block
2

You can't, you'll need deal with it through promises, but you could try do it like this:

$http.get('URL').success(function(data){
    angular.copy(data, $scope.data);
});

$.fullCalender({
    data: $scope.data
});

but most people would just do

$http.get('URL').success(function(data){
    $.fullCalender({
        data: data
    });
});

If whatever your fullCalender object is doesn't work with async data, you might need to wrap it in something like ng-if or force it to redraw when the data has been supplied. You can also force the controller to not load until the data is loaded by using the route resolve.

Comments

2

Here is a practical answer, courtesy of user Kirill Slatin who posted the answer as a comment. Practical use example at the bottom of the answer.

If, like me, you need to use that response object as a scope variable, this should work:

$http.get('URL').success(function(data){

$scope.data = data;
$.fullCalender = $scope.data;
$scope.$apply()
});

$scope.$apply() is what will persist the response object so you can use that data.

-

Why would you need to do this?

I'd been trying to create an "edit" page for my recipes app. I needed to populate my form with the selected recipe's data. After making my GET request, and passing the response data to the $scope.form, I got nothing... $scope.$apply() and Kirill Slatin helped big time. Cheers mate!

Here's the example from my editRecipeController:

  $http.get('api/recipe/' + currentRecipeId).then(
    function (data) {
      $scope.recipe = data.data;
      $scope.form = $scope.recipe;
      $scope.$apply()
    }
);

Hope that helps!

Comments

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.