承诺再次承诺(Angular JS)

使用HTTP和基于请求的初始代码更新/请查看post的底部:

我最近在AngularJS学习曲线上发布了几个问题,SO社区也很精彩。 我曾经是一名传统的C程序员,我以前编程并且最近开始编写我自己的离子/ Angular JS应用程序。 在将自定义函数转换为promise时,我正在努力处理传统异步调用的promise版本。 我不认为我真的理解,我发现各种非常人为的例子。 我很感激一些帮助。 我有一些代码无效,我有一些概念性的问题:

我们来看看这个简单的function:

angular.module('zmApp.controllers').service('ZMDataModel', function() { return { getMonitors: function () { return monitors; } } 

getMonitors是一个简单的函数,它基本上返回一组监视器。 但这就是问题:当应用程序首次启动时,我会调用一个http工厂执行http get,然后填充此监视器列表。 此http工厂与此服务不同,但在此服务中调用setMonitor方法来填充数组。 填充数组时,名为“monitorsLoaded”的变量设置为1.当此变量设置为1时,我确定已加载监视器。

现在,我有一个名为“MontageCtrl”的控制器。 我想在显示视图之前等待监视器加载。 在之前的post中,有人建议我使用路由解析,但我必须先将我的getMonitors转换为promise。 所以这就是我所做的:

 angular.module('zmApp.controllers').service('ZMDataModel', function($q) { getMonitors: function () { var _deferred = $q.defer(); if (monitorsLoaded!=0) { console.log ("**** RETURNING MONITORS *****"); _deferred.resolve(monitors); } console.log ("*** RETURNING PROMISE ***"); return _deferred.promise; }, 

接下来,在app.js我连接路由如下:

  .state('app.montage', { data: {requireLogin:false}, resolve: { message: function(ZMDataModel) { console.log ("Inside app.montage resolve"); return ZMDataModel.getMonitors(); } }, 

最后我修改了我的控制器以获取承诺:

 angular.module('zmApp.controllers').controller('zmApp.MontageCtrl', function($scope,$rootScope, ZMHttpFactory, ZMDataModel,message) { //var monsize =3; console.log ("********* Inside Montage Ctrl"); 

它似乎基于日志,我从来没有进入蒙太奇控制台。 路由解析似乎正在等待,而我的日志显示一段时间后,monitorLoaded被设置为1。

我有几个概念性问题:

a)在我按照例子制作的函数getMonitors中,为什么人们返回_deferred.promise但只分配_deferred.resolve? (也就是为什么不回来?)。 它会自动返回吗?

b)我注意到如果我将var _deferred定义移动到我的服务并且移出了它的子函数,它确实有效,但是具有相同路由依赖性的下一个视图没有。 我很困惑。

c)最后,我准备在某个地方,当涉及到路由解析时,服务和工厂之间存在区别,因为服务仅被实例化一次。 我也很困惑,因为在人们使用的一些路由解析示例中,我正在使用.state。 在这个阶段,我深陷于自己的困惑之中。 有人可以帮忙澄清一下吗? 所有我真正想要的是等待各种观点,直到monitorLoaded为1.我想通过路由解析和承诺来做到这一点,所以我一劳永逸地得到了承诺。

补充:这是HTTP工厂代码以及app.run代码,它在应用程序首次启动时调用此代码。 仅供参考,http工厂运行良好 – 当我制作ZMDataModel时出现的问题 – 我希望这是所有控制器使用的中央数据存储库 – 因此他们不必每次都调用HTTP Factory来访问数据,我可以控制何时需要调用HTTP工厂

 angular.module('zmApp.controllers').factory('ZMHttpFactory', ['$http', '$rootScope','$ionicLoading', '$ionicPopup','$timeout','ZMDataModel', function($http, $rootScope, $ionicLoading, $ionicPopup, $timeout,ZMDataModel) { return { getMonitors: function() { var monitors = []; var apiurl = ZMDataModel.getLogin().apiurl; var myurl = apiurl+"/monitors.json"; return $http({ url: myurl, method: 'get' }) //http .then(function(response) { var data = response.data; //console.log("****YAY" + JSON.stringify(data)); // $rootScope.$broadcast ('handleZoneMinderMonitorsUpdate',monitors); $ionicLoading.hide(); ZMDataModel.setMonitors(data.monitors); ZMDataModel.setMonitorsLoaded(1); //monitors = data.monitors; return ZMDataModel.getMonitors(); }, function (result) { console.log ("**** Error in HTTP"); $ionicLoading.hide(); ZMDataModel.setMonitorsLoaded(1); //$ionicPopup.alert ({title: "Error", template:"Error retrieving Monitors. \nPlease check if your Settings are correct. "}); return ZMDataModel.getMonitors(); } ); //then }, //getMonitors 

以下是app.run中首先调用此代码的代码:

 .run(function($ionicPlatform, $ionicPopup, $rootScope, $state,ZMDataModel, ZMHttpFactory) { ZMDataModel.init(); var loginData = ZMDataModel.getLogin(); if ( loginData.username && loginData.password && loginData.url && loginData.apiurl) { console.log ("VALID CREDENTIALS. Grabbing Monitors"); // this calls http factory getMonitors that eventually populated the ZMDataModel // monitors array and sets monitorsLoaded to 1 ZMHttpFactory.getMonitors(); } } 

我终于解决了所有问题。 我最初的尝试有各种各样的问题。 我最终解决的解决方案在这里我是否正确地回复了这个承诺

学习:

a)将HTTP进入工厂分离,将数据模型分离到另一个服务中,不必要地使生活复杂化。 但这种分离不是问题。 事实上,承诺在上面编码的方式,在第一次运行时,如果monitorsLoaded为0,它将简单地返回延迟的承诺,并且没有“.success”或类似的构造让我再次进入解析代码块。

b)使我在循环中运行的最大问题是推迟或拒绝只是设置状态。 返回总是必须是承诺 – 它会返回你设置的状态。 我假设返回d.promise总是意味着返回“进行中”。