问题:在控制器方法中使用this.promise.then(function(){})
函数似乎创建了$ rootScope:infDig循环,尽管该方法的返回值不会改变。值得注意的是,当删除.then()行时,无限摘要循环消失了(参见代码)。
代码:
视图中的{{ getSelectedProjects() }}
和附加控制器中的以下方法
var vm = this;
vm.getSelectedProjects = function() {
if (angular.isUndefined(vm.hello)) {
vm.hello = "hello"
vm.promise = $q.when("hello i am a resolved promise")
}
vm.promise //In my original code, this promise is returned by a service (MyService.getPromise()). The resolved value of the returned promise may change which is why the service needs to be called at each digest cycle.
.then(function (ans) {
vm.hello = ans;
}); //remove .then(...) function and there is no infinite digest loop anymore
return vm.hello;
}
问题:为什么这会创建一个无限的摘要循环,尽管返回的值不会改变?我怎么能避免它(我非常需要那个承诺的结果)?。
我摇摇欲坠的想法:我想这与事实有关.then()每次都会返回一个新的承诺。文档没有说明它,但如果该promise每次都附加到控制器对象(vm),这可能被视为控制器的状态更改并触发新的摘要循环,重新计算vm.getSelectedProjects()并再次向控制器等附加新的承诺。
修改 我的假设是“不稳定的想法”#34;似乎不完全正确或完整,因为此代码仍然存在问题:
vm.getSelectedProjects = function() {
if (angular.isUndefined(vm.hello)) {
vm.hello = "hello"
}
$q.when("hello i am a resolved promise")//this object is not attached to the controller object
.then(function () {});
return vm.hello;
}
答案 0 :(得分:0)
基于遇到的问题和评论,我们为在项目中使用promises创建了编码指南。发现分享它很有意思,因为我没有在任何地方看到这个记录。
Promise是令人惊奇的对象,但错误的用法会让人头疼。因此,我们有一些指导原则:
这是应该在模型,管理器或其他服务中的结构,尽可能接近数据源。不在控制器中:
var myApiMethod = function() {
//We call "caching" the fact that this method is executed only if $scope.item is undefined.
If (angular.isUndefined($scope.item) {
$scope.item = {}
$http(xxx).then(function(value){
$scope.item = value;
});
return $scope.item
}
}
然后控制器只返回myApiMethod的答案。您可能需要检查'myService.myApiMethod()!= {}'。
在服务中,我们可以定义缓存行为(例如:每2小时从后端检索数据,在某个事件中清除缓存等)。只要有一个单一的事实来源(来自本案例中的服务,而不是来自控制器)关于要返回的对象,您可以轻松地玩这个。
*为什么不在视图或表达式评估调用的控制器方法中使用promises(例如{{vm.getMyApiMethodResult()}} *:
为什么不将myApiMethod放入控制器中进行缓存(如上面的实现),以确保myApiMethod只被调用一次并避免无限的摘要循环?原因有三:
请记住:本指南仅适用于表达式评估中调用的控制器函数。您可能需要在事件处理程序调用的控制器函数中使用promise(单击等),这很好,因为在每个角度的摘要周期都不会调用这些函数。