在循环中链接嵌套的promise

时间:2021-02-13 19:37:07

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.

有一个控制器使用$ http.get()从服务器获取数据的服务来说国家及其城市。国家和城市都是json数组。

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?

我想链接国家和城市的获取,以便将doAfterCountriesAndCitiesLoaded()作为最后一个链处理。如何通过正确的错误处理将此代码转换为promise链接?

2 个解决方案

#1


1  

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:

当你需要并行执行一些promises时,你需要$ q.all,并且为了连锁动作,你需要返回你的承诺:

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);

#2


1  

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.

返回service.getCountries调用的结果(这是一个promise)并使用then和catch链接结果。在前者的回调函数中调用doAfterCountriesAndCitiesLoaded并在后者的句柄中处理任何错误。

var getCountries = function () {
   return service.getCountries()
      .then(function (countries) {
        ....
};

getCountries()
   .then(function(countries){
       doAfterCountriesAndCitiesLoaded(countries);
   }
   .catch(error){
       //handle errors
   }

#1


1  

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:

当你需要并行执行一些promises时,你需要$ q.all,并且为了连锁动作,你需要返回你的承诺:

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);

#2


1  

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.

返回service.getCountries调用的结果(这是一个promise)并使用then和catch链接结果。在前者的回调函数中调用doAfterCountriesAndCitiesLoaded并在后者的句柄中处理任何错误。

var getCountries = function () {
   return service.getCountries()
      .then(function (countries) {
        ....
};

getCountries()
   .then(function(countries){
       doAfterCountriesAndCitiesLoaded(countries);
   }
   .catch(error){
       //handle errors
   }