AngularJS : Prevent error $digest already in progress when calling $scope.$apply()

前端 未结 28 2707
伪装坚强ぢ
伪装坚强ぢ 2020-11-21 22:31

I\'m finding that I need to update my page to my scope manually more and more since building an application in angular.

The only way I know of to do this is to call

28条回答
  •  梦如初夏
    2020-11-21 23:25

    See http://docs.angularjs.org/error/$rootScope:inprog

    The problem arises when you have a call to $apply that is sometimes run asynchronously outside of Angular code (when $apply should be used) and sometimes synchronously inside Angular code (which causes the $digest already in progress error).

    This may happen, for example, when you have a library that asynchronously fetches items from a server and caches them. The first time an item is requested, it will be retrieved asynchronously so as not to block code execution. The second time, however, the item is already in cache so it can be retrieved synchronously.

    The way to prevent this error is to ensure that the code that calls $apply is run asynchronously. This can be done by running your code inside a call to $timeout with the delay set to 0 (which is the default). However, calling your code inside $timeout removes the necessity to call $apply, because $timeout will trigger another $digest cycle on its own, which will, in turn, do all the necessary updating, etc.

    Solution

    In short, instead of doing this:

    ... your controller code...
    
    $http.get('some/url', function(data){
        $scope.$apply(function(){
            $scope.mydate = data.mydata;
        });
    });
    
    ... more of your controller code...
    

    do this:

    ... your controller code...
    
    $http.get('some/url', function(data){
        $timeout(function(){
            $scope.mydate = data.mydata;
        });
    });
    
    ... more of your controller code...
    

    Only call $apply when you know the code running it will always be run outside of Angular code (e.g. your call to $apply will happen inside a callback that is called by code outside of your Angular code).

    Unless someone is aware of some impactful disadvantage to using $timeout over $apply, I don't see why you couldn't always use $timeout (with zero delay) instead of $apply, as it will do approximately the same thing.

提交回复
热议问题