在循环中链接嵌套的promise

时间:2015-03-05 07:12:38

标签: angularjs angular-promise

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

当前实施

服务

service.getCountries = function() {
    return $http.get('url');
}

service.getCities = function(country) {
    return $http.get('url' + country);
}

控制器

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

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

2 个答案:

答案 0 :(得分:1)

返回service.getCountries调用的结果(这是一个承诺),并将结果与​​thencatch相关联。在前一个回调函数中调用doAfterCountriesAndCitiesLoaded,后者处理任何错误。

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

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

答案 1 :(得分:1)

当您需要并行执行多个承诺时,您需要$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);