So I have an AngularJS service listening for some events. On the handling of these events I need to call different controllers and ultimately load a new view. In one event handler I am using $location.path() then calling $rootScope.apply() to trigger the routing to the controller. This works fine for that event, but in others I get the following error: $rootScope:inprog Action Already In Progress
. I'm guessing that it works in the first scenario because $rootScope.apply() is called from another callback function inside the listener function, where as the other handlers try to call it just from the event listener function.
//angular service
$rootScope.$on('MY_EVENT', function (event, msg) {
MyClass.doSomething(msg, function (response) {
$location.path("/view1");
$rootScope.$apply(); //WORKS FINE
});
});
$rootScope.$on('MY_OTHER_EVENT', function (event, msg) {
$location.path("/view2");
$rootScope.$apply(); //ERROR
});
How can I get it to work for all event handlers?
plnkr example
There are a few ways to deal with this. The easiest way to deal with this is to use the built in $timeout, and a second way is if you are using underscore or lodash (and you should be), call the following: $timeout(function(){ //any code in here will automatically have an apply run afterwards });
$scope.$apply() This function is used to execute an expression in Agular. The function expression is optional and you can directly use $apply(). This is used to run watcher for the entire scope. $rootScope.$digest()
The problem is that it's performing $digest
on $rootScope
twice in quick succession and it throws the error when there's an overlap. To get around this, you can simply wrap both calls to $location.path()
in $timeout
, as you have done the first time in your plnkr example. This will force it to wait for the $digest
cycle to complete.
You may also remove the explicit calls to $rootScope.$apply()
.
$rootScope.$on('FIRST_EVENT', function(event, msg) {
$timeout(function() {
$location.path("/view1");
});
});
$rootScope.$on('SECOND_EVENT', function(event, msg) {
$timeout(function() {
$location.path("/view2");
});
});
Note:
This code is based on the plnkr example, which is slightly different than the code in the original post.
Reference:
wait for end of $digest cycle
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With