jmona789 jmona789 - 18 days ago 5
AngularJS Question

Promise is not waiting for nest promises before resolving

I have this initialization function that runs to set up global dependancies for my app I am using the npm package angular-global-resolve. The package works fine, the problem is I have one big promise with nested promises in it in the initialization function and the main promise resolves before the nested ones, meaning certain things are not set the first time the app runs. How do I fix this?

My code:

in routes.js:

globalResolveProvider.addGlobalDependenciesTo($stateProvider, {
getGlobalDependacies: function ($http, $rootScope, $cookies) {
return $http.get('/__/env.json')
.then(function(response) {
console.log('then0')
$rootScope.apiUrl = response.data.apiUrl;
$rootScope.googleMapsApiKey = response.data.googleMapsApiKey;
$rootScope.currentLocationLat = 40.7589;
$rootScope.currentLocationLng = 73.9851;
var hotelId = ''
if ($cookies.get('hotel') === undefined){
console.log('if 1')
$http.get($rootScope.apiUrl + '/hotels')
.then(function(dbHotels){
console.log('then1')
hotelId = dbHotels.data[0]._id
$cookies.put('hotelId', hotelId)
})
}
if ($cookies.get('userId') === undefined){
console.log('if 2')
$http.get($rootScope.apiUrl + '/users')
.then(function(dbUsers){
console.log('then2')
var index = dbUsers.data.length - 1
var userId = dbUsers.data[index]._id
$cookies.put('userId', userId)
$rootScope.$broadcast('update-itinerary-icon')
})
}
})
.then(function(){
console.log("parent then is resolved")
})
}
})


The console is logging:

then0
if 1
if 2
parent then is resolved
then1
then2


why does the parent then resolve before
then1
and
then2
?

Answer

When you do

$http.get($rootScope.apiUrl + '/hotels')

Or:

$http.get($rootScope.apiUrl + '/users')

This only begins an HTTP request. Flow continues in the parent promise, without waiting for the nested GET to complete. And then the parent resolves as usual.

If you want to make the parent wait for a child promise, you must make the parent return a promise:

return $http.get($rootScope.apiUrl + '/hotels')

Now, if you want to make the parent wait for multiple child promises, you must return a promise which composes multiple promises. Inject $q into your function, and use this as your return statement:

return $q.all(
    $http.get($rootScope.apiUrl + '/hotels'),
    $http.get($rootScope.apiUrl + '/users')
);

If you want conditional logic, then you could try something like this:

return $q.all(
    ($cookies.get('hotel') === undefined)
    ? $http.get($rootScope.apiUrl + '/hotels')
    : $q.resolve(),
    ($cookies.get('userId') === undefined)
    ? $http.get($rootScope.apiUrl + '/users')
    : $q.resolve()
);

This makes it wait for an already completed promise, in the case where no work is necessary.

You can also add your .then() to the $http.get() in the above example.