Search code examples
javascriptangularjsangularjs-scope

Is calling $scope.$digest within $scope.$on fundamentally incorrect?


I have inherited some AngularJS code, and I know very little about it (the code and Angular both). The code that I inherited contains several places where $scope.$digest is called within a $scope.$on method within a controller. For example:

$scope.$on("ScriptEditorEnabled", function (e, enabled) {
    $scope.scriptEditorDisabled = !enabled;
    $scope.$digest();
});

In my context, this is causing the popular $digest already in progress error (AngularJS : Prevent error $digest already in progress when calling $scope.$apply()). Isn't an $on method part of the $scope object, and thus, any changes to its data would be picked up automatically? If so, doesn't that mean that calling $digest within one (either directly or indirectly), just plain incorrect?

I've been simply removing these calls, seemingly without any loss in functionality, and the errors go away. Is there any dangers I should be aware of when doing this?


Solution

  • $scope.$on gets called in response to $scope.$broadcast or $scope.$emit. The $scope.$on should always assume that it runs inside a digest loop. Neither $apply nor $digest calls should be needed inside the $on handler.

    Angular is pretty clear about it in the When to use $scope.$apply(). If you dispatch events from non-angular environments, you should wrap the $emit or $broadcast call in $apply instead of calling it in the event handler. Example:

    $rootScope.$apply($rootScope.$broadcast('recievedMsg', msg));
    

    It's dispatcher responsibility to enter the digest loop if it knows there isn't one started already.