Angular承诺不等待决心

时间:2014-04-09 06:55:01

标签: jquery arrays angularjs angularjs-scope

所以我似乎仍然无法正确理解承诺。我正在使用角度解析来阻止控制器在promise解决之前加载视图,但它不能按预期工作。我做错了什么?

这是我的服务

commonServicesModule.factory('helpdeskPriority', function($q, $timeout, getCommonList) {
        var items;
        return {
            get: function(params) {
                var defer = $q.defer();
                $timeout(function() {
                    getCommonList.helpdesk.priority().success(function(result) {
                        console.log('waited for long tym ');
                        defer.resolve(result);
                    });
                }, 0);
                return defer.promise;
            },
        }
    });

从控制器调用

helpdeskPriority.get().then(function(data) {     
            console.log(data);
        });

我的优先功能

priority: function() {
                        return $http({
                            url: urlc.getListing.priority,
                            data: {
                                "params": JSON.stringify({})
                            },
                            method: 'POST',
                        });
                    },

3 个答案:

答案 0 :(得分:1)

你没有得到的主要是.factory()如何运作。它应该被赋予一个返回值的函数。它不需要自己的.get()函数,Angular将为您{$get: <your factory function>}创建一个提供者对象。

然后你需要意识到当你使用resolve时,依赖关系应该解析为promise。这意味着当注入器获得helpDeskPriority依赖项的值时,它将获得一个promise作为值(因为它调用提供程序的$get方法,这是您的工厂函数)。在运行控制器之前,解析机制将等待该承诺得到解决,helpDeskPriority依赖性等于它所解决的值。

因此,请将工厂代码更改为:

commonServicesModule.factory('helpdeskPriority', function($q, $timeout, getCommonList) {
        var items;
        var defer = $q.defer();
        $timeout(function() {
             getCommonList.helpdesk.priority().success(function(result) {
                 console.log('waited for long tym ');
                 defer.resolve(result);
             });
        }, 0);
        return defer.promise;
    });

然后您的控制器变为:

 function myController($scope, ..., helpDeskPriority) {
      console.log(helpDeskPriority); // will already have the correct value
 }

答案 1 :(得分:0)

将您的代码放入封闭可能会帮助您

commonServicesModule.factory('helpdeskPriority', function($q, $timeout, getCommonList) {
  var items;
  return {
    get: function(params) {
      var defer = $q.defer();
      (function (deferred, list) {
        $timeout(function() {
          list.helpdesk.priority().success(function(result) {
            console.log('waited for long tym ');
            deferred.resolve(result);
          });
        }, 0);
      })(defer, getCommonList);
      return defer.promise;
    },
  }
});

答案 2 :(得分:-1)

您的代码是正确的。您只需要在绑定到模板的then()回调中设置范围变量。 Angularjs将自动触发刷新:

helpdeskPriority.get().then(function(data) {     
            console.log(data);
            @scope.myLazyLoadedData = data;  // async initialization
        });

此外:

以下jsfiddle http://jsfiddle.net/jeromerg/43F28/2/通过使用$http + $timeout模拟$q来电来重现您的示例。这个例子表明一切都很好!如果您仍然无法获得预期的行为,那么请您扩展jsfiddle示例并解释您的期望吗?所以,我们可以更好地了解正在发生的事情......

备注:

如果您想在$http来电结束前阻止显示您的观看或部分观看,那么您可以将 ng-if="callFinished" 属性添加到您想要的元素中隐藏在你的模板中。并在控制器中的回调中设置范围标志callFinished,如下所示:

helpdeskPriority.get().then(function { 
    $scope.callFinished = true; 
});

如果您希望在$http调用结束之前保持上一个视图,然后更改为此视图,那么您应该从上一个视图中进行$http调用并执行视图在那里更改$http.success()回调。备选方案:您可以使用路由提供程序的resolve属性,如下所述:Delaying AngularJS route change until model loaded to prevent flicker。但是,一旦调用了新视图的控制器功能,我就不会认为可以保留以前的视图。