Reputation: 49185
There is a controller that gets say countries and their cities using the service which uses $http.get()
to fetch data from the server. Both the countries and the cities are json arrays.
Current implementation
service
service.getCountries = function() {
return $http.get('url');
}
service.getCities = function(country) {
return $http.get('url' + country);
}
controller
var getCountries = function () {
service.getCountries()
.success(function (countries) {
angular.forEach(countries, function (country) {
// process country
getCities(country);
});
})
.error(function () {
alert('failed to load countries');
});
};
var getCities = function (country) {
service.getCities(country)
.success(function (cities) {
angular.forEach(cities, function (city) {
// process city
});
})
.error(function () {
alert('failed to load cities of ' + country);
});
};
var doAfterCountriesAndCitiesLoaded = function () {
// do
}
getCountries();
doAfterCountriesAndCitiesLoaded();
I want to chain the fetching of countries and cities so that doAfterCountriesAndCitiesLoaded()
is processed as a last chain.
How this code can be converted to promise chaining with proper error handling?
Upvotes: 1
Views: 571
Reputation: 7852
Return the result of the service.getCountries
call (which is a promise) and chain the result with then
and catch
. In the former's callback function call doAfterCountriesAndCitiesLoaded
and in the latter's handle any errors.
var getCountries = function () {
return service.getCountries()
.then(function (countries) {
....
};
getCountries()
.then(function(countries){
doAfterCountriesAndCitiesLoaded(countries);
}
.catch(error){
//handle errors
}
Upvotes: 1
Reputation: 101662
When you need to execute a number of promises in parallel, you need $q.all
, and in order to chain actions, you need to return your promises:
var getCountries = function () {
return service.getCountries()
.then(function (result) {
return $q.all(result.data.map(getCities));
}).catch(function (result) {
var message = 'failed to load countries';
console.log(message);
throw new Error(message);
});
};
var getCities = function (country) {
return service.getCities(country)
.then(function (result) {
angular.forEach(result.data, function (city) {
// process city
});
}).catch(function () {
var message = 'failed to load cities of ' + country;
console.log(message);
throw new Error(message);
});
};
var doAfterCountriesAndCitiesLoaded = function () {
// do
};
getCountries().then(doAfterCountriesAndCitiesLoaded);
Upvotes: 1