2015-03-05 3 views
1

Существует контроллер, который говорит, что страны и их города используют службу, которая использует $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() обрабатывается в качестве последней цепи.
Как этот код может быть преобразован в целую цепочку с правильной обработкой ошибок?

ответ

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

Зачем нужно «бросать новую ошибку (сообщение)»? –

+0

Это необходимо для того, чтобы 'getCountries' знал, что одна из операций getCities не удалась. В этом отношении я бы сказал, что имеет смысл выбросить ошибку в 'catch' функции' getCountries'. – JLRishe

+0

Ну, еще немного вопросов: 1) улов используется для обработки defer.reject() afaik. Может ли уловка также обрабатывать «throw new Error()» тоже? 2) Есть ли преимущество использования q в этом случае/catch над успехом/ошибкой http в вышеприведенном коде? –

1

Возврат результата вызова service.getCountries (что является обещанием) и связать результат с then и catch. В функции обратного вызова в первом вызове doAfterCountriesAndCitiesLoaded и в дескрипторе последнего имеются ошибки.

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

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

Собственно служба возвращает само обещание, а чем его результат (см. править). Нужно ли ждать, пока города будут загружены между getCountries и doAfterCountriesAndCitiesLoaded? –

+0

Да, но вам нужно вернуть обещание, возвращенное из службы, а затем ждать его разрешения, используя цепочку 'then'. Что касается городов, вы можете использовать '$ q.all' и решить, когда все будет обработано. Имеет смысл? – Christian

+0

Я не уверен, что этот ответ совершенно прав: я не думаю, что «успех» возвращает обещание, а это означает, что вы не можете вызывать «then» на его возвращаемом значении для дальнейшей обработки. Однако вы можете просто вызвать стандартную функцию 'then' непосредственно на обещание, возвращенное' $ http' для обработки результатов. –

Смежные вопросы