为什么使用 CryptoJS 的哈希计算会导致 Angular 中的 $rootScope:infdig 错误?
Why would a hash computation using CryptoJS cause a $rootScope:infdig error in Angular?
我有一个简单的页面,当有人在页面中输入字符串时,它会显示字符串的哈希值。我发现该页面有一个 JavaScript 错误
错误:[$rootScope:infdig]http://errors.angularjs.org/1.2.26/$rootScope/infdig?p0=10&p1=%5B%5B%22sha1…75651%2C1080464653%2C-772792499%5D%2C%5C% 22sigBytes%5C%22%3A20%7D%22%5D%5D
页面的一个非常简化的版本是
<html lang="en">
<head>
<script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/rollups/sha1.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js"></script>
<script>
function MyCtrl($scope) {
$scope.sha1 = function(pwd) {
return CryptoJS.SHA1(pwd);
};
}
</script>
</head>
<body>
<div class="app" ng-app ng-controller="MyCtrl">
<span ng-bind="sha1('bar')"></span>
</div>
</body>
</html>
可用作 Plunker http://plnkr.co/edit/vmBtH8B2EKsdcfZVGlMH。
我在原始页面中尝试做的是在有人输入表单字段时重新计算哈希值,输入字段定义如下所示
<input id="password" ng-model="password" type="text" placeholder="Password">
而 ng-bind 实际上是 ng-bind="sha1(password)"
,但是 Plunker 中的简单静态案例表现出相同的行为。
我了解到 infdig 错误与过多的 $digest 循环有关,但我不知道这里会发生什么。看起来哈希计算触发了错误,因为从 sha1 函数返回静态字符串不会导致错误。
提供 ng-bind="sha1('bar')"
使摘要循环不稳定,每次 sha1 函数 returns 一个不同的对象(引用不同)并且您的摘要循环必须再次 运行 以稳定它并且每次摘要循环再次计算 ng-bind 函数表达式,并继续计算直到达到最大限制集 (10)。您也可以通过在您的范围方法中执行 return []
轻松地重现此问题。这只是将函数表达式绑定到 ng-bind
的不太好的做法的副作用,因为每个摘要周期 运行s,如果使用它应该仔细评估。
一个简单的解决方案是在您的密码或任何其他触发器上绑定 ng-change/ng-blur 事件,并将 ng-bind 绑定到 属性 而不是函数表达式。
angular.module('app',[])
.constant('Crypto', window.CryptoJS);
function MyCtrl($scope, Crypto) {
$scope.encrypt = function() {
$scope.encrypted = Crypto.SHA1($scope.password);
};
}
<html lang="en" ng-app="app">
<head>
<script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/rollups/sha1.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js"></script>
</head>
<body>
<div class="app" ng-app ng-controller="MyCtrl">
<input id="password" ng-model="password" type="password" placeholder="Password" ng-change="encrypt()">
<span ng-bind="encrypted"></span>
</div>
</body>
</html>
为了更好地使用 DI,我将 crpto 放在常量中并在需要的地方注入它。
我有一个简单的页面,当有人在页面中输入字符串时,它会显示字符串的哈希值。我发现该页面有一个 JavaScript 错误
错误:[$rootScope:infdig]http://errors.angularjs.org/1.2.26/$rootScope/infdig?p0=10&p1=%5B%5B%22sha1…75651%2C1080464653%2C-772792499%5D%2C%5C% 22sigBytes%5C%22%3A20%7D%22%5D%5D
页面的一个非常简化的版本是
<html lang="en">
<head>
<script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/rollups/sha1.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js"></script>
<script>
function MyCtrl($scope) {
$scope.sha1 = function(pwd) {
return CryptoJS.SHA1(pwd);
};
}
</script>
</head>
<body>
<div class="app" ng-app ng-controller="MyCtrl">
<span ng-bind="sha1('bar')"></span>
</div>
</body>
</html>
可用作 Plunker http://plnkr.co/edit/vmBtH8B2EKsdcfZVGlMH。
我在原始页面中尝试做的是在有人输入表单字段时重新计算哈希值,输入字段定义如下所示
<input id="password" ng-model="password" type="text" placeholder="Password">
而 ng-bind 实际上是 ng-bind="sha1(password)"
,但是 Plunker 中的简单静态案例表现出相同的行为。
我了解到 infdig 错误与过多的 $digest 循环有关,但我不知道这里会发生什么。看起来哈希计算触发了错误,因为从 sha1 函数返回静态字符串不会导致错误。
提供 ng-bind="sha1('bar')"
使摘要循环不稳定,每次 sha1 函数 returns 一个不同的对象(引用不同)并且您的摘要循环必须再次 运行 以稳定它并且每次摘要循环再次计算 ng-bind 函数表达式,并继续计算直到达到最大限制集 (10)。您也可以通过在您的范围方法中执行 return []
轻松地重现此问题。这只是将函数表达式绑定到 ng-bind
的不太好的做法的副作用,因为每个摘要周期 运行s,如果使用它应该仔细评估。
一个简单的解决方案是在您的密码或任何其他触发器上绑定 ng-change/ng-blur 事件,并将 ng-bind 绑定到 属性 而不是函数表达式。
angular.module('app',[])
.constant('Crypto', window.CryptoJS);
function MyCtrl($scope, Crypto) {
$scope.encrypt = function() {
$scope.encrypted = Crypto.SHA1($scope.password);
};
}
<html lang="en" ng-app="app">
<head>
<script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/rollups/sha1.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js"></script>
</head>
<body>
<div class="app" ng-app ng-controller="MyCtrl">
<input id="password" ng-model="password" type="password" placeholder="Password" ng-change="encrypt()">
<span ng-bind="encrypted"></span>
</div>
</body>
</html>
为了更好地使用 DI,我将 crpto 放在常量中并在需要的地方注入它。