$digest不久之后$watch定义触发“$apply已经在进行中.“错误

$digest soon after $watch definition triggers "$apply already in progress..." error

本文关键字:apply 错误 进行中 digest 之后 定义 watch      更新时间:2023-09-26

>我是一个棱角分明的菜鸟,我试图理解为什么以下触发"$apply已经在进行中......" 错误。

这是代码(它实际上几乎直接来自文档:https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$digest)

<!DOCTYPE html>
<html>
<head>
    <script src="js/lib/angular.js"></script>
    <script>
    var app = angular.module('app', []);
    app.controller('MainController', ['$scope', function(scope) {
        scope.name = 'misko';
        scope.counter = 0;
        //A
        scope.$watch('name', function(newValue, oldValue) {
            scope.count++;
        });
        //B
        scope.$digest();
    }]);
    </script>
</head>
<body>
    <div ng-app='app' ng-controller="MainController">
    </div>
</body>
</html>

而且,这是小提琴:https://jsfiddle.net/zLny2faq/5/

我收到著名的"$apply已经在进行中"错误,但为什么呢?

我想知道为什么摘要周期甚至没有被调用就触发?

换句话说,我只是声明监视侦听器 (@comment A) 并通过调用 $digest() (@comment B) 来触发它们。但是当我显式调用 $digest() 时,似乎它以某种方式被更快地调用并出错。为什么会这样?

请指教。

name 变量在监视 yes 之前设置,但所有监视在初始化时都会调用一次:

每个角度文档

将观察程序注册到作用域后,侦听器 fn 为 异步调用(通过 $evalAsync)以初始化观察程序。在 在极少数情况下,这是不可取的,因为侦听器是在以下情况下调用的 watchExpression 的结果没有改变。检测此方案 在侦听器 fn 中,您可以比较 newVal 和 oldVal。如果 这两个值是相同的 (===),然后侦听器被调用 due 到初始化。

^ 可以通过以下方式照顾:

$scope.$watch('name', function(newValue, oldValue) {
  if (newValue !== oldValue) {
    // will only run if the value changes, on initial load the newvalue = oldvalue so it won't run this code.
  }
});

如果确实需要调用$digest,可以使用

$timeout(function(){
    scope.$digest();
}, 0);

小提琴