【问题标题】:AngularJS Promises, $q, deferAngularJS 承诺,$q,延迟
【发布时间】:2013-09-11 12:07:27
【问题描述】:

编辑

第一个答案是优雅的,但是,正如在这个问题和关于 stackoverflow 的另一个问题中多次指出的那样,问题是服务和控制器在数据实际到达之前运行它们的东西。

(对第一个答案的最后评论:)

是的,问题是 API 调用在服务运行后完成 并将所有内容返回给控制器,请参见此处 screencast.com/t/uRKMZ1IgGpb7 ...这是我的基本问题,我怎么能 等待所有部分的数据到达?

就像我重复说的那样,我们如何在成功检索数据后创建一个填充数组的服务,以及在所有这些发生后控制器获取数据,因为你可以在我的屏幕截图中看到,事情以不同的顺序运行。


我有这个代码:

 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;

对于我的一生,我无法理解为什么在将结果数组传递给 defer 时必须设置超时?

原理不应该是这样,defer等待信息到来然后返回promise吗?那1秒有什么意义?据我了解,defer 应该能够等待 API 返回结果并返回承诺的数据。

我真的很困惑,在过去的两个小时里我一直把头撞在墙上,因为我没有在控制器中接收任何数据,只有当我在那里设置超时时。

【问题讨论】:

  • 您的意思是要将所有$http.get 返回值放入$q.all 吗?
  • 我将所有输出的数组都放入聚合数据中,这样我就可以将该对象传递给 $q defer。我想了解实际发生了什么,这是一个 jsFiddle,jsfiddle.net/tjnWQ .... 承诺在这里如何运作。
  • 说实话,我充满了挫败感。现在已经快 6 周了妨碍制作实际可用产品的框架:)。我屈服了,在这本书上花了很多钱packtpub.com/angularjs-web-application-development/book
  • "第一个答案是优雅的,"...问题是什么?
  • 当时,我无法在 Angular 中掌握和使用 Promise 的概念,我在互联网上发现了一些误导性的文章,其中有人实际上使用了 $timeout [somehow] 并连接了多个承诺的回归,长话短说,我脑子里的想法一团糟,下面的答案中的@dluz让一切都清楚了。

标签: javascript angularjs promise q


【解决方案1】:

恕我直言,我认为$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()

希望对您有所帮助,或者如果您需要完整的工作示例,请告诉我,我可以提供! :)

【讨论】:

  • +1 for $q.all,更干一点:[14, 15, 16, 17].map(function (id) { return $http.get('../wordpress/api/core/get_category_posts/?category_id=' + id); });
  • 是的!同意plalx!只是不想用一些甜蜜的额外代码来混淆他:)
  • 太棒了!它看起来肯定比我的更优雅:)。关于我上面的头痛:我是否应该假设 $q.all 将等待所有 API 调用完成,然后在最终数组中提供数据。也可以使用 .then() 在控制器中等待的数据?
  • 那本书是我开始写的,我会读好几遍,我会继续努力,直到我把它做好:)。
  • Arthur,我有同一本书 - 事实上,我很幸运能在伦敦亲自认识这本书的一位作者(彼得·培根):) 我真的喜欢这本书。看看第 84 - 94 页(尤其是第 91 页),您将对$q.all 有一个更好的了解。乐于助人!
【解决方案2】:

$http.get 调用是异步的,但您不会等到它们全部完成后再解决延迟。在这里它适用于超时只是因为您很幸运调用有时间在 1 秒内完成,但这根本不可靠。

我不会在这里重申一个完整的解决方案,但请查看my answer 以了解另一个类似问题。

【讨论】:

  • 我知道,这正是我所说的,超时是演示中大量使用的道具,而不是与现实生活中的 API 对话。这就是我要找的,一种等待并在两边显示数据的方法(Service->Controller->View)
  • 嘿 plalx,你能看到第一个答案和我的评论吗,代码很干净,但是有一个时间问题screencast.com/t/uRKMZ1IgGpb7 - 数据仍然在之后到达。
  • @ArthurKovacs 你能用所有相关代码创建一个小提琴吗?
  • 嘿,Palx,这就是重点,我之前尝试过(这里有另一个问题),来自数组的数据没有问题,但是在我的机器上使用 REAL 端点时,我一直遇到这个问题.尽管如此,我还是会用实际的代码 sn-ps 来摆弄一下。几分钟后
  • 我正在考虑和github.com/mgonto/restangular/blob/master/README.md一起玩会尝试其他的东西。 PLALX,我希望今天晚上有时会在 heroku 上推送我的应用程序,我会回来提供链接。
猜你喜欢
  • 2017-05-08
  • 2015-03-08
  • 1970-01-01
  • 2015-06-22
  • 1970-01-01
  • 1970-01-01
  • 2013-09-27
  • 2015-03-27
  • 2023-03-21
相关资源
最近更新 更多