简体   繁体   English

AngularJS承诺,$ q,推迟

[英]AngularJS Promises, $q, defer

EDIT 编辑

The first answer is the elegant one, but, as stated a few times in this question and another questions on stackoverflow, the problem is that the service and the controller run their thing before the data actually arrives. 第一个答案是优雅的答案,但是,正如在这个问题中提到的几次以及有关stackoverflow的另一个问题,问题是服务和控制器在数据实际到达之前运行它们的东西。

(Last comment on the first answer:) (最后评论第一个答案:)

Yes, the problem is that the API calls finish AFTER the service runs and returns everything to the controller, see here screencast.com/t/uRKMZ1IgGpb7 ... That's my BASE question, how could I wait on all the parts for the data to arrive? 是的,问题是API调用在服务运行后完成并将所有内容返回给控制器,请参见此处screencast.com/t/uRKMZ1IgGpb7 ...这是我的基础问题,我怎么能等待数据的所有部分到到达?

It's like I'm saying it on repeat, how do we make a service that populates the array after the successful data retrieval, and the controller getting data after all this happens , because as you can see in my screenshot, things run in a different order. 这就像我在重复上说的那样, 我们如何在成功的数据检索之后创建一个填充数组的服务,并且控制器在所有这些之后获取数据 ,因为正如您在我的屏幕截图中看到的那样,事情在不同的情况下运行订购。


I have this code: 我有这个代码:

 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;

For the life of me I can't understand why do I have to put a timeout when passing the resulting array to defer ? 对于我的生活,我无法理解为什么在传递结果数组延迟时我必须暂停?

Shouldn't the principle be like, defer waits for the information to come and then returns the promise? 不应该原则如何,推迟等待信息再来回信承诺? What is the point of that 1 second there? 那1秒有什么意义呢? From what I understand defer should be able to wait as long as needed for the API to return the result and the return the promised data. 根据我的理解,延迟应该能够等待API返回结果并返回承诺数据所需的时间。

I'm really confused, I've banged my head against the walls for the last two hours because I was not receiving any data in my controller, only when I put that timeout there. 我真的很困惑,过去两个小时我的头撞到了墙上,因为我没有在控制器中收到任何数据,只有当我把那个超时放在那里时。

IMHO I think there's a much clever (and elegant) way to do this with $q.all . 恕我直言我认为有一个非常聪明(和优雅)的方式与$q.all这样做。

Please take a look at the code below. 请看下面的代码。

I am assuming that you want to return the data at once with all the results aggregated on a big array. 我假设您想要立即返回数据,并将所有结果聚合在一个大数组上。

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

You can see above that the aggregatedData is only generated once all the async calls are completed via the $q.all . 你可以看到上面说的aggregatedData所有异步调用都通过完成只产生一次$q.all

You just need to include the service as dependency into one of your controllers, for example, and call the service like this myService.getAllData() 例如,您只需将服务作为依赖项包含在您的某个控制器中,然后像这样调用服务myService.getAllData()

Hope that helps or just let me know if you need a full working example and I can provide one! 希望有帮助或只是让我知道你是否需要一个完整的工作示例,我可以提供一个! :) :)

The $http.get calls are async, but you aren't waiting until they are all completed before resolving the deferred. $http.get调用是异步的,但是在解决延迟之前你不会等到它们全部完成。 Here it works with the timeout simply because your are lucky that the calls have time to complete within 1 second, however this isin't reliable at all. 这里的超时工作只是因为你很幸运,呼叫有时间在1秒内完成,但这根本不可靠。

I will not reiterate a complete solution here, but have a look at my answer for another similar issue. 我不会在这里重申一个完整的解决方案,但请看看对另一个类似问题的回答

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM