承诺再次承诺(Angular JS)

时间:2015-04-14 12:18:37

标签: javascript jquery angularjs

根据请求更新了HTTP和初始代码/请查看帖子底部:

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

让我们来看看这个简单的功能:

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

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

现在,我有一个名为" MontageCtrl"的控制器的视图。我想在显示视图之前等待监视器加载。在之前的帖子中,有人建议我使用路由解析,但我必须先将我的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();
               
            }
}




1 个答案:

答案 0 :(得分:0)

我终于解决了所有问题。我最初的尝试有各种各样的问题。我最终解决的解决方案是Am I returning this promise correctly?

学习:

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

b)让我在循环中跑来跑去的最大的事情就是推迟或拒绝只是设置状态。返回总是必须是承诺 - 它会返回你设置的状态。我假设返回d.promise总是意味着返回“正在进行中”。