简体   繁体   English

在绑定到内部带有$ http的函数时运行到无限的摘要周期

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

I need to generate http link for a tag. 我需要生成HTTP链接, a标签。 For that reason I put in html line 出于这个原因,我放入了html

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

in controller it defined as: 在控制器中它定义为:

$scope.getLink = function(inputUrl){

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

}

Why AngularJS ends up in infinite cycle? 为什么AngularJS会以无限循环结束? What is the right design? 什么是正确的设计?

As explained in another answer, watched expressions are evaluated on every digest and the resulting value is compared to their previous value - dirty checking. 正如另一个答案所解释的那样,在每个摘要上评估监视的表达式,并将结果值与其先前的值进行比较 - 脏检查。 If there is a change, another iteration of the digest starts because a change in one value might cause a change in another. 如果存在更改,则摘要的另一次迭代开始,因为一个值的更改可能导致另一个值的更改。

If there is a circular dependency (including, the circle of one, ie the same expression is different every time), it results in an infinite loop that Angular stops after 10 iterations. 如果存在循环依赖(包括,一个圆,即每次相同的表达式不同),则会导致Angular在10次迭代后停止的无限循环。

Specifically, your getLink function's return value is a promise (the return value of $http), and Angular bindings do not "wait" on a promise. 具体来说,你的getLink函数的返回值是一个promise($ http的返回值),而Angular绑定不会在promise上“等待”。

What you want to do is to kick start the $http call and in its handler assign the return value to a ViewModel property that would be bound to <a> : 你想要做的是启动$http调用并在其处理程序中将返回值赋给将绑定到<a>的ViewModel属性:

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

You can call getLink , for example, when your controller runs. 例如,您可以在控制器运行时调用getLink

In the View you just bind url to ng-href (not href ) attribute: 在视图中,您只需将url绑定到ng-href (而不是href )属性:

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

Once you add an Angular expression in View like {{expression}} , it would be added to watch list of current scope. 在像{{expression}}这样的View中添加Angular表达式后,它将被添加到当前范围的监视列表中。

Angular uses a mechanism called dirty checking to archive two way binding. Angular使用一种称为dirty checking的机制来存档双向绑定。 Each time some specific events happen, Angular will go through the watch list to check whether the watched value has changed or not, this action is called as digest loop . 每次发生某些特定事件时,Angular将通过监视列表检查监视值是否已更改,此操作称为digest loop

Here some specific events consist of user input, model change, $http requests finish, etc. As you are using a function getLink in the expression, each time when Angular trigger a dirty check/digest loop, this function will be executed once again to check whether its return result has changed. 这里的some specific events包括用户输入,模型更改,$ http请求完成等。当您在表达式中使用函数getLink时,每当Angular触发脏检查/摘要循环时,此函数将再次执行到检查其返回结果是否已更改。

The problem is, the function getLink here is a $http request, after it's executed, Angular will triggered another round dirty check ,which will execute this function again ... Bang, it's an infinite loop. 问题是,这里的函数getLink是一个$ http请求,在执行之后,Angular将触发另一轮脏检查,它将再次执行此函数...... Bang,这是一个无限循环。

Conclusion: do not add any $http call in angular expression. 结论:不要在角度表达式中添加任何$ http调用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM