Make function wait for $http response in AngularJS

16.7k views Asked by At

I have a method seatClicked() that calls getUserID() to get the user id corresponding to the session atribute 'user'. There is a table that contains the username and user id(unique). The following is the definition of seatClicked()

$scope.seatClicked = function() {
    promise = $scope.getUserID();
    promise.then(function(results){
        $scope.seatID.userID = results; // store the user id in $scope.seatID.userID
    });
}

This is the definition for getUserID()

$scope.getUserID = function() {
    var deferred = $q.defer();
    $http({
        method : 'POST',
        url : 'http://localhost:8080/AirlineApp/getUserID',
        headers : {
            'Content-Type' : 'application/json'
        }
    }).then(function(data){
        alert("userID:"+data)
         deferred.resolve(data);
    })
    return deferred.promise;
};

The variable 'results' returned by $http.then() is always undefined, whereas if I use $http.success() I am able to retrieve the user id.

I want to fetch the user id before further processing. Is there any way for the function to wait till the data is fetched from the database? P.S. I tried callback as well, no luck.

Edit: I am able to fetch the id and store it (thanks all), but it takes much longer than the time taken to execute my next operation(not presented here). Can I stall that operation till I am assured of the id?

2

There are 2 answers

1
FlavienBert On

$http returns a special promise different from the standard promise like here https://github.com/promises-aplus/promises-spec

If you use $http you need to retrieve your data like this :

$http
  .success(success) 
  .error(error) ...

But you can use standard promise by wrapping the $http promise in your service using $q like this :

var defer = $q.defer();
var http = $http({
    url: SharedFactory.endPoint + '/stats',
    method: 'GET',
    params: params
});

http.success(function(stats) {
      defer.resolve(stats);
    })
    .error(function() {
      defer.reject("Failed to get stats");
    });

  return defer.promise;
6
Dmitri Algazin On

what we did in our project, added PromiseUtils service for any REST calls

.service("PromiseUtils", function($q) {
    return {
        getPromiseHttpResult: function (httpPromise) {
            var deferred = $q.defer();
            httpPromise.success(function (data) {
                deferred.resolve(data);
            }).error(function () {
                deferred.reject(arguments);
            });
            return deferred.promise;
        }
    }
})

and use it nice and easy

var anyCall  = $http({
        method: 'POST',
        url: 'http://localhost:8080/AirlineApp/getUserID',
        headers: {
            'Content-Type': 'application/json'
        }
    });

PromiseUtils.getPromiseHttpResult(anyCall).then(function(result){
   console.log("result", result);
})

or

PromiseUtils.getPromiseHttpResult($http.get('/api/get/call'))
.then(function(result){
    console.log("result", result);
})

PromiseUtils.getPromiseHttpResult($http.post('/api/post/call', data))
.then(function(result){
   console.log("result", result);
})

if you need error() function, just add as second parameter

PromiseUtils.getPromiseHttpResult($http.get('/api/get/call'))
.then(function(result){
    console.log("result", result);
}, function (arguments) {
    console.log("fail", arguments);         
})