在绑定到内部$http函数时运行无限摘要循环

Running into infinite digest cycle while binding to function that has $http inside

本文关键字:无限 运行 循环 函数 绑定 内部 http      更新时间:2023-09-26

我需要为a标签生成http链接。出于这个原因,我输入了html

<a href="{{getLink(url)}}">My link</a>

在控制器中,它定义为:

$scope.getLink = function(inputUrl){
    $http.get(inputUrl).success(function(data){/*.....*/});
}

为什么 AngularJS 最终会陷入无限循环?什么是正确的设计?

如另一个答案中所述,在每个摘要上评估监视的表达式,并将结果值与其以前的值进行比较 - 脏检查。如果存在更改,则会启动摘要的另一个迭代,因为一个值的更改可能会导致另一个值的更改。

如果存在循环依赖关系(包括 1 的圆,即相同的表达式每次都不同),则会导致 Angular 在 10 次迭代后停止的无限循环。

具体来说,getLink函数的返回值是一个承诺($http 的返回值),并且 Angular 绑定不会"等待"一个承诺。

您要做的是启动$http调用,并在其处理程序中将返回值分配给将绑定到<a>的 ViewModel 属性:

function getLink(){
  $http.get(inputUrl)
      .success(function(data){
         $scope.url = data.data;
      });
}

您可以调用getLink,例如,当控制器运行时。

在视图中,您只需将url绑定到ng-href(而不是href)属性:

<a ng-href="url">My Link</a>

一旦您在视图中添加 Angular 表达式,例如 {{expression}} ,它将被添加到当前范围的监视列表中。

Angular 使用一种称为 dirty checking 的机制来存档双向绑定。每次发生一些特定事件时,Angular 都会浏览监视列表以检查监视值是否已更改,此操作称为 digest loop

这里some specific events包括用户输入、模型更改、$http请求完成等。当您在表达式中使用getLink函数时,每次当 Angular 触发脏检查/摘要循环时,都会再次执行此函数以检查其返回结果是否已更改。

问题是,这里getLink的函数是一个$http请求,执行后,Angular 会触发另一轮脏检查,它会再次执行这个函数......砰,这是一个无限循环。

结论:不要在角度表达式中添加任何$http调用。