gpt4 book ai didi

javascript - 解决 $rootScope :infdig Infinite $digest Loop

转载 作者:数据小太阳 更新时间:2023-10-29 04:31:02 27 4
gpt4 key购买 nike

我了解了无限摘要循环的基本概念以及它是如何发生的,但我遇到了问题。这是一个演示我的代码和问题的 fiddle :

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

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

基本上,我必须对可能尚未加载的数据做出决定,因此我需要使用 then() 等待 promise 解决。我有一个名为用户的 promise 。在代码中有两个不同的地方我调用了用户的 then()。

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

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

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

$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();
});

最佳答案

所以我终于弄清楚了我自己的问题,并认为我会为其他人回答这个问题,以防其他人发现此信息有用。

修复的关键与两个概念有关: Angular promise Angular 监视。通过了解并同时应用这 2 个概念,修复实际上非常简单。

你放在 $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 是相同的 promise ,而不是 then() 创建的新 promise ,因此应用周期稳定。

为了完整起见,这里是更新的 jsfiddle:

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

关于javascript - 解决 $rootScope :infdig Infinite $digest Loop,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24650403/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com