AngularJS Promises, $q, отложить
ИЗМЕНИТЬ
Первый ответ - изящный, но, как было сказано несколько раз в этом вопросе и еще один вопрос о stackoverflow, проблема в том, что служба и контроллер запускают свое дело до того, как данные действительно поступят.
(Последний комментарий к первому ответу:)
Да, проблема в том, что вызовы API завершаются ПОСЛЕ запуска службы и возвращает все к контроллеру, см. здесь screencast.com/t/uRKMZ1IgGpb7... Что мой вопрос BASE, как я мог подождите на всех частях для получения данных?
Мне нравится, что я повторяю, , как мы делаем службу, которая заполняет массив после успешного поиска данных, а контроллер получает данные после всего этого, потому что, как вы можете см. на моем снимке экрана, все работает в другом порядке.
У меня есть этот код:
var deferred = $q.defer();
$http.get('../wordpress/api/core/get_category_posts/?category_id=14 ').success(function(data) {
//we're emptying the array on every call
theData = [];
catName = data.category.slug;
theData = data;
theData.name = catName;
aggregatedData.push(theData);
});
$http.get('../wordpress/api/core/get_category_posts/?category_id=15 ').success(function(data) {
theData = [];
catName = data.category.slug;
theData = data;
theData.name = catName;
aggregatedData.push(theData);
});
$http.get('../wordpress/api/core/get_category_posts/?category_id=16 ').success(function(data) {
theData = [];
catName = data.category.slug;
theData = data;
theData.name = catName;
aggregatedData.push(theData);
});
$http.get('../wordpress/api/core/get_category_posts/?category_id=17 ').success(function(data) {
theData = [];
catName = data.category.slug;
theData = data;
theData.name = catName;
aggregatedData.push(theData);
});
//deferred.resolve(aggregatedData);
$timeout(function() {
deferred.resolve(aggregatedData);
}, 1000);
/*//deferred.reject('There is a connection problem.');
if (myservice._initialized) {
$rootScope.$broadcast('postsList', deferred.promise);
}*/
//myservice._initialized = true;
myservice = deferred.promise;
return deferred.promise;
В течение жизни я не могу понять, почему мне нужно поставить тайм-аут при передаче результирующего массива для отсрочки?
Не должен ли принцип быть подобным, отсрочка ждет, когда информация придет, а затем вернет обещание? В чем смысл 1 секунды? Из того, что я понимаю, отсрочка должна быть в состоянии ждать столько, сколько потребуется, чтобы API возвращал результат и возвращал обещанные данные.
Я действительно смущен, я ударил головой о стены в течение последних двух часов, потому что я не получал никаких данных в своем контроллере, только когда я помещал туда этот тайм-аут.
Ответы
Ответ 1
IMHO Я думаю, что там есть очень умный (и элегантный) способ сделать это с помощью $q.all
.
Пожалуйста, ознакомьтесь с приведенным ниже кодом.
Я предполагаю, что вы хотите сразу вернуть данные со всеми результатами, собранными в большом массиве.
var myApp = angular.module('myApp', []);
myApp.factory('myService', function ($http, $q) {
return {
getAllData: function () {
return $q.all([
$http.get('../wordpress/api/core/get_category_posts/?category_id=14'),
$http.get('../wordpress/api/core/get_category_posts/?category_id=15'),
$http.get('../wordpress/api/core/get_category_posts/?category_id=16'),
$http.get('../wordpress/api/core/get_category_posts/?category_id=17')
]).then(function (results) {
var aggregatedData = [];
angular.forEach(results, function (result) {
aggregatedData = aggregatedData.concat(result.data);
});
return aggregatedData;
});
}
};
});
Вы можете видеть выше, что aggregatedData
генерируется только после завершения всех асинхронных вызовов с помощью $q.all
.
Вам просто нужно включить службу как зависимость в один из ваших контроллеров, например, и вызвать службу, подобную этой myService.getAllData()
Надеюсь, что поможет или просто дайте мне знать, если вам нужен полный рабочий пример, и я могу его предоставить!:)
Ответ 2
Вызовы $http.get
являются асинхронными, но вы не дожидаетесь их завершения до разрешения отложенных. Здесь он работает с тайм-аутом просто потому, что вам повезло, что у вызовов есть время для завершения в течение 1 секунды, однако это не является надежным вообще.
Я не буду повторять полное решение здесь, но посмотрю мой ответ на другую аналогичную проблему.