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 секунды, однако это не является надежным вообще.

Я не буду повторять полное решение здесь, но посмотрю мой ответ на другую аналогичную проблему.