Handling Angular's "Digest Already in Progress"

2015-09-17 | #angular, #javascript, #solution, #webdev

Sometimes value updates seem to take ages before finally arriving in the template or you simply want to update a scope value somewhere decoupled from the scope, like a jQuery-event-handler for example.

In those cases you'd have to trigger the scope's digest cycle manually.

Here you have two options: $scope.$digest and $scope.$apply.

The first is faster but only handles the scope in an isolated way, not handling any exceptions, the second one evaluates up to the $rootScope and handles exceptions via the $exceptionHandler. So I'd opt for the second one in most cases.

But triggering a digest cycle (while perfectly possible) manually has a serious problem, since there is no good way to find out if the $scope is currently in a digest cycle and two cycles simultaneously result in the aforementioned exception. So, we'll have to wait for the next possible slot before executing our cycle.

Again there are two good possibilities for this:

Either use

$timeout(function(){ /* code you'll want to digest ASAP */ });

or use something like underscore's

_.defer(function(){ $scope.$apply(); });

Both defer the execution until the next synced slot, while Angular's $timeout manages the digestion automatically.