我得到了无限摘要循环的基本概念以及它是如何发生的,但我遇到了问题。这是一个演示我的代码和问题的小提琴:
在jsfiddle控制台中,您将看到无限的摘要循环。
基本上我必须对可能尚未加载的数据做出决定,所以我需要等待使用then()解析的承诺。我有一个叫做用户的承诺。代码中有两个不同的地方,我在用户上调用then()。
对于数字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();
});
答案 0 :(得分:13)
所以我终于找到了自己的问题,并认为如果其他人可能会发现此信息有用,我会为其他人解答。
修复的关键在于两个概念:角度承诺和角度手表。通过了解并应用这两个概念,修复实际上非常简单。
你放在$ scope上的所有东西都被观看了#39;包括功能。每次观看的内容都会更改$ scope。$ apply()会再次运行以应用更改。如果范围函数(例如:$ scope.isAdmin())改变其返回值,则应用&#39; apply&#39;到下一个它将触发另一个“应用”,直到事情稳定并且返回值不会发生变化。
但是在我的代码中,我返回了user.then(...),它只返回一个新的promise(由于返回值不断变化,这使得应用程序循环继续进行)。
在我的isAdmin()函数中,我需要将其返回值推迟到用户实际加载(任何其他返回值都没有意义)。所以我更改了代码以检查用户异步调用是否已通过检查$ scope.user解决,如果是,则返回有效的isAdmin值。如果$ scope.user仍未定义,我只会返回我已创建的承诺。
我将$ scope.isAdmin()更改为:
$scope.isAdmin = function() {
if ($scope.user) {
return $scope.user.isAdmin;
}
return user;
};
这与原始代码具有相同的效果,而不会触发无限应用循环。具体来说,如果$ scope.user没有解决,我们仍然像以前一样返回一个promise,方法是返回用户var。但请注意,用户var是相同的承诺,而不是then()创建的新承诺,因此应用周期稳定。
只是为了完整性,这里是更新的jsfiddle: