javascript – 求解$rootScope:infdig Infinite $digest循环

前端之家收集整理的这篇文章主要介绍了javascript – 求解$rootScope:infdig Infinite $digest循环前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我得到了无限摘要循环的基本概念以及它是如何发生的,但我遇到了问题.这是一个演示我的代码和问题的小提琴:

http://jsfiddle.net/eS5e5/1/

在jsfiddle控制台中,您将看到无限的摘要循环.

基本上我必须对可能尚未加载的数据做出决定,所以我需要等待使用then()解析的承诺.我有一个叫做用户的承诺.代码中有两个不同的地方,我在用户调用then().

>就在我定义它之后.我需要根据它设置范围变量.
>在另一个范围方法中,$scope.isAdmin()

对于数字2,可能会问为什么我不直接在$scope.isAdmin()方法中使用$scope.user.问题是,在用户的异步请求返回之前,可以调用$scope.isAdmin(),在这种情况下,我需要在从$scope.isAdmin()返回之前“阻塞”.

我的问题是,$scope.isAdmin()是什么让角度认为“观察”变量已经改变并且摘要周期需要再次运行?

$scope.isAdmin()实际上并没有改变任何东西.

这是精简代码

HTML:

<body ng-controller='myController'>  
  <div ng-if='isAdmin()'>Hi! <strong>{{ user.username }}</strong> is an Admin!!!</div>
  <div ng-if='!isAdmin()'>Hi! <strong>{{ user.username }}</strong> is NOT an Admin!!!</div>
</body>

和JS:

angular.module('myApp',[])
  .factory('myService',function($q,$timeout) {
    return {        
      getUser: function() {
        var deferred = $q.defer();

        $timeout(function() {
          deferred.resolve({ username: 'me',isAdmin: true });
        },2000);

        return deferred.promise;
      }
    };
  })
  .controller('myController',function($scope,$q,myService) {      
    var getUserDeferred = $q.defer();
    var user = getUserDeferred.promise;
    user.then(function(user) {
      $scope.user = user;
      return user;
    });

    $scope.getUser = function() {
      return myService.getUser().then(function(user) {
        getUserDeferred.resolve(user);
      });
    };

    $scope.isAdmin = function() {
      return user.then(function(user) {
        return user.isAdmin;
      });
    };

    $scope.getUser();
  });

解决方法

所以我终于找到了自己的问题,并认为我会为其他人回答它,以防其他人发现这个信息有用.

修复的关键在于两个概念:角度承诺和角度手表.通过了解并应用这两个概念,修复实际上非常简单.

你在$scope上放置的所有东西都是’看过’包括功能.每次观看的内容都会更改$scope.$apply()会再次运行以应用更改.如果范围函数(例如:$scope.isAdmin())将其返回值从“应用”更改为下一个,则会触发另一个“应用”,直到事情稳定并且返回值不变.

但是在我的代码中,我返回了user.then(…),它只返回一个新的promise(由于返回值不断变化,因此使应用周期保持不变).

在我的isAdmin()函数中,我需要推迟其返回值,直到用户实际加载(任何其他返回值都没有意义).所以我更改了代码以检查用户异步调用是否已通过检查$scope.user解决,如果是,则返回有效的isAdmin值.如果$scope.user仍未定义,我只会返回我已经创建的promise.

我将$scope.isAdmin()更改为:

$scope.isAdmin = function() {
  if ($scope.user) {
    return $scope.user.isAdmin;
  }

  return user;
};

这与原始代码具有相同的效果,而不会触发无限应用循环.具体来说,如果$scope.user尚未解决,我们仍然会像以前一样返回一个promise,方法是返回用户var.但请注意,用户var是相同的承诺,而不是then()创建的新承诺,因此应用周期稳定.

只是为了完整性,这里是更新的jsfiddle:

http://jsfiddle.net/eS5e5/2/

猜你在找的JavaScript相关文章