我正确地回复了这个承诺吗?

时间:2015-04-14 19:32:04

标签: javascript angularjs

我在服务中有一个函数getMonitors。 getMonitors返回监视器对象列表。如果监视器对象为空,它将通过http抓取监视器并将对象存储在监视器对象数组中,然后将其返回。该函数被编码为promise。我知道http会返回一个承诺,但我的功能可能会也可能不会使用http - 所以我将它与我自己的承诺重叠(参见下面的代码)

控制器可以调用getMonitors(0)或getMonitors(1)。 0表示如果由于之前的呼叫而已将其加载到监视器阵列中,请不要再次加载它。 (1)表示强制从HTTP重新加载数组

服务和关联的getMonitors按以下方式编码:

angular.module('zmApp.controllers').service('ZMDataModel', ['$http', '$q',
      function($http, $q) {
        // var deferred='';
        var monitorsLoaded = 0;
        var monitors = [];

        getMonitors: function(forceReload) {
          console.log("** Inside ZMData getMonitors with forceReload=" + forceReload);
          var d = $q.defer();
          if ((monitorsLoaded == 0) || (forceReload == 1)) // monitors are empty or force reload
          {
            console.log("ZMDataModel: Invoking HTTP Factory to load monitors");
            var apiurl = loginData.apiurl;
            var myurl = apiurl + "/monitors.json";
            $http.get(myurl)
              .success(function(data) {
                // console.log ("HTTP success got " + JSON.stringify(data));
                monitors = data.monitors;
                console.log("promise resolved inside HTTP success");
                monitorsLoaded = 1;
                return d.resolve(monitors);
              })
              .error(function(err) {
                console.log("HTTP Error " + err);
                monitors = [];
                console.log("promise resolved inside HTTP fail");
                // I know I need to reject here, not resolve. I'll get to it. For now lets assume I need an empty monitors list if there was an error
                return d.resolve(monitors);
              });
            console.log("promise deferred inside HTTP inside getMonitors");
            return d.promise;

          } else // monitors are loaded
          {
            console.log("Returning pre-loaded list of " + monitors.length + " monitors");
            return d.resolve(monitors);
          }

        },

我将路由设置为getMonitors作为依赖项,如下所示:

.state('app.montage', {
  data: {
    requireLogin: false
  },
  resolve: {
    message: function(ZMDataModel) {
      console.log("Inside app.montage resolve");
      return ZMDataModel.getMonitors(0);
    }
  },
  url: "/montage",
  views: {
    'menuContent': {
      templateUrl: "templates/montage.html",
      controller: 'zmApp.MontageCtrl',

    }
  }
})

使用它的示例控制器的编码如下:

angular.module('zmApp.controllers').controller('zmApp.MontageCtrl', function($scope, $rootScope, ZMDataModel, message) {

  $scope.monitors = [];
  console.log("Inside MontageCtrl waiting for monitors to load...");

  $scope.monitors = message;
  // this line returns undefined when getMonitors tries to return a preloaded monitor list
  console.log("I have received the monitors inside Montage and there are " + $scope.monitors.length);
  // console.log("***CALLING FACTORY");
  //ZMHttpFactory.getMonitors().then(function(data) //{
  //                                  $scope.monitors = data;
  // console.log("I GOT " + $scope.monitors);
  //    });

  $scope.doRefresh = function() {
    console.log("***Pull to Refresh");
    $scope.monitors = [];

    var refresh = ZMDataModel.getMonitors(1);
    refresh.then(function(data) {
      $scope.monitors = data;
      $scope.$broadcast('scroll.refreshComplete');
    });

  };
});

我遇到的问题是第一次运行时,监视器列表为空,因此ZMData从HTTP URL加载监视器,视图显示完美。当我切换到另一个视图并返回到该视图时,我看到它记录了ZMData正在返回预加载的监视器列表(我知道它们已填充,因为我在ZMData getMonitor else部分中打印出计数)。但是,当" else"时,返回到控制器的内容是不确定的。 getMonitors的一部分命中。

这可能意味着我没有在getMonitors中正确地返回承诺"否则"一部分。

任何帮助将不胜感激

1 个答案:

答案 0 :(得分:1)

啊,我终于围绕着承诺。 我们不能返回d.resolve()。这只是一个国家。你总是需要返回d.promise,如果已经解决,它将返回解决方案。人。这让我很生气。我想我在3个不同的SO问题之后终于得到了承诺的基本信息。我希望教程更清楚。每个人都只返回d.promise并且没有人真正清楚地说明d.promise返回承诺的状态 - 通过解决或拒绝改变。

正确的代码是:

getMonitors: function (forceReload) {
            console.log ("** Inside ZMData getMonitors with forceReload="+forceReload);
            var d = $q.defer();
           if ((monitorsLoaded == 0) || (forceReload == 1)) // monitors are empty or force reload
           {
               console.log ("ZMDataModel: Invoking HTTP Factory to load monitors");
                var apiurl = loginData.apiurl;
                var myurl = apiurl+"/monitors.json";
                $http.get(myurl)
                    .success(function(data)
                    {
                       // console.log ("HTTP success got " + JSON.stringify(data));
                        monitors = data.monitors;
                        console.log ("promise resolved inside HTTP success");
                        monitorsLoaded = 1;
                        d.resolve(monitors);
                    })
                    .error (function (err)
                    {
                        console.log ("HTTP Error " + err);
                        monitors = [];
                        console.log ("promise resolved inside HTTP fail");
                        d.resolve (monitors);
                });
                return d.promise;

           }
            else // monitors are loaded
            {
                console.log ("Returning pre-loaded list of "+monitors.length+" monitors");
                 d.resolve(monitors);
                return d.promise;
            }

        }