角度承诺不等待解决



所以我似乎仍然没有正确理解promise。我使用角度解析来防止控制器在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',
                        });
                    },

您不太了解.factory()是如何工作的。应该给它一个返回值的函数。它不需要自己的.get()函数,Angular将使用{$get: <your factory function>}为您创建一个提供程序对象。

然后你需要意识到,当你使用决心时,依赖应该转化为承诺。这意味着,当注入器获得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
 }

将代码放入闭包中可能有助于

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;
    },
  }
});

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

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

添加:

下面的jsfiddlehttp://jsfiddle.net/jeromerg/43F28/2/通过用$timeout+$q模拟$http调用来重现您的示例。这个例子表明一切都很好!如果你仍然不能得到预期的行为,你能扩展jsfiddle的例子并解释你到底期望什么吗?这样,我们就可以更好地了解发生了什么…

备注:

如果要防止在$http调用结束前显示视图或视图的一部分,则可以将ng-if="callFinished"属性添加到要隐藏在模板中的元素中。并在位于控制器中的回调中设置作用域标志callFinished,如下所示:

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

如果您想在$http调用结束之前一直停留在上一个视图中,然后更改到此视图,则应在上一视图中进行$http调用,并在那里的$http.success()回调中执行视图更改。备选方案:您可以使用路由提供程序的resolve属性,如下所述:延迟AngularJS路由更改,直到加载模型,以防止闪烁。但是,一旦调用了新视图的控制器功能,我认为就不可能继续显示以前的视图。

最新更新