有时我的Angular代码失败了,有以下异常信息。**错误。10 $digest() iterations reached.终止!**我不知道那里发生了什么,也没有得到解释Angular的绑定如何工作。在这篇文章中,我将分享如何避免这个问题,以及如何在Angular应用程序中使用记忆化技术获得更好的性能。
$digest问题
所以,当你收到错误信息**Error:10 $digest() iterations reached.终止!**在你的Angular应用程序中,它实际上意味着什么?好吧,为了回答这个问题,我们必须了解Angular是如何检测变化并立即显示在用户界面上的。
这个算法非常简单--当你通过绑定在html模板中输出一个变量或函数时,就会创建一个观察者。在应用程序的生命周期中,观察者的表达式被多次调用,其结果与之前的值相匹配,如果值不同,就会触发一个相关事件,并在模板中显示新的值。要获得更多关于检测变化的信息,你可以参考这篇文章。但现在只需了解可能的问题是一个返回对象数组的函数,该函数在摘要循环中被调用。
这是很简单的演示。假设我们想遍历控制器函数中生成的用户列表:
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
var data = [
{firstName: 'John', lastName: 'Smith'},
{firstName: 'Andrei', lastName: 'Kaleshka'}
];
$scope.getUsers = function() {
var result = [];
angular.forEach(data, function (user) {
result.push({fullName: user.firstName + ' ' + user.lastName});
});
return result;
}
});
<div ng-repeat="user in getUsers()">
</div>
这个问题的发生是因为getUsers() ,尽管数组项目的属性是相同的,但每次调用都会返回不同的结果:
var res1 = [{fullName: 'John Smith'}, {fullName: 'Andrei Kaleshka'}];
var res2 = [{fullName: 'John Smith'}, {fullName: 'Andrei Kaleshka'}];
res1 === res2; // false
这就是为什么Angular的digest循环会无限地调用getUsers 。错误信息错误。达到10次$digest()迭代。中止!通知我们这个问题。
解决方案
为了解决这个问题,我们可以对函数的结果进行缓存。为此,我喜欢使用Lo-Dash的memoize函数:
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
var data = [
{firstName: 'John', lastName: 'Smith'},
{firstName: 'Andrei', lastName: 'Kaleshka'}
];
$scope.getUsers = _.memoize(function() {
var result = [];
angular.forEach(data, function (user) {
result.push({fullName: user.firstName + ' ' + user.lastName});
});
return result;
});
});
总结
使用这个技术,我们改善了Angular应用程序的性能,摆脱了异常**错误。达到10个scope` ,实现了返回对象数组的函数,这些函数可以在Angular的模板中使用。