【angular】$apply already in progr

2019-01-27  本文已影响0人  天已微蓝_9aca

如果我们使用了angularJS中的$scope.$apply()或者$scope.$digest(),我们很可能会遇到类似下面的错误:
Error: [$rootScope:inprog] $apply already in progress

为什么?
因为angularJS框架本身已经在做脏数据检测了,我们没有必要再手动调用$apply或者$digest。

解决
1.angular中的$scope中提供了一个$$phase变量,如果这个变量的值是"$digest" 或者"$apply",就代表angular自身已经在做脏值检测了,不需要我们再去调用$apply或者$digest;否则的话就需要我们手动调用了。
($scope.$$phase || $scope.$root.$$phase) ? '' : $scope.$apply();

$scope.$apply(function() {
            $scope.mydata = 'data changed';
        });

避免使用以上代码,而用以下代码代替

$timeout(function() {
            $scope.mydata = 'data changed';
        });

什么时候需要手动调用$apply或者$digest?
1.controller中有异步操作,比如ajax回调,timeout延时等。
可以这么理解:由于异步(延迟)的存在,当开始执行回调函数的时候,angularJS自身controller中的脏值检测已经结束,无法检测到回调函数导致数据的变化。
2.在JQuery代码中修改$scope中的数据。
这种情况是在angular框架之外操作$scope中的数据,angular不能检测到数据变化是正常的。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
    <script src="../src/angular.min.js"></script>
    <script src="../src/jquery-3.3.1.min.js"></script>
</head>
<body >
    <div id="div1" ng-app="myApp" ng-controller="ctrl1">
        <div>{{ text }}</div>
        <button id="btn1">Click</button>
    </div>
<script>
    var app = angular.module('myApp', []);
    app.controller('ctrl1', function($scope) {
        $scope.text = "value1";
        setTimeout(function() {
            $scope.text = "value changed after time out";
            $scope.$apply();//必需手动进行脏值检测,否则数据无法刷新到界面
        },1000);

        $(function() {
            $("#btn1").click(function() {
                $scope.text = "value changed by jquery";
                $scope.$apply();
            });
        })
    });

</script>
</body>
</html>

但是代码中最好不要使用$digest、$apply、$$phase这些$scope中的私有的属性或者方法,因为这代表了你没有按照angular的方式来组织代码。比如setTimeout,完全可以用angular中的$timeout代替而不是通过$apply来补救。

上一篇下一篇

猜你喜欢

热点阅读