1

In a large application where you might have a large scope, if you call $scope.$apply multiple times in rapid succession, can you get a 'scope already in progress' error?

E.g, I have a directive which is linked to the bootstrap switch plugin. This directive simply shows an on/off switch which the user can click to toggle a boolean value as true/false. Each time the user clicks this button, my directive does a $scope.$apply() in which one scope variable is changed to reflect the new state of the switch (on or off).

I was worried that if a user clicks the switch in rapid succession, I might get the 'digest already in progress' error. However, that isn't the case, each time things go very smoothly and the scope value is updated everywhere instantly despite multiple $scope.$apply() calls being fired.

Is this because $scope.$apply is optimized somehow so it doesn't run a full digest, but only updates those values which were changed, or is it just because my scope is relatively small at the moment so the full digest isn't taking long to be run?

Ali
  • 261,656
  • 265
  • 575
  • 769
  • You shouldn't need to call $scope.$apply hardly ever. If you provide an example I'm sure we could help. – Zack Argyle Aug 27 '13 at 22:24
  • @ZackArgyle I do give an example in the question, basically a directive for the bootstrap-switch, each time the user clicks the switch, it triggers a call to $scope.$apply to update the changed variable – Ali Aug 27 '13 at 22:28
  • Oh, I really don't think someone will click faster than the digest cycle. Try it out, see if you can click fast enough! – Zack Argyle Aug 27 '13 at 22:31
  • @ZackArgyle That's correct, I can't. But will the cycle always stay this fast or will it slow down when the scope grows bigger? – Ali Aug 27 '13 at 22:33
  • 1
    @click-update If you want to be extra sure, set up a safe apply function like this dude. [Angular Safe Apply](https://coderwall.com/p/ngisma) – Zack Argyle Aug 28 '13 at 16:10

1 Answers1

2

Javascript is single-threaded. Each call to $apply() runs synchronously. The only way to get that error is to call $apply() from within a function that has been called in the Angular context.

I've had arrays of arrays of multiple large blocks of shown/hidden blocks with no problems. Javascript and Angular are pretty optimized.

Jim Cote
  • 1,746
  • 3
  • 15
  • 26
  • What happens if each call to `$scope.$apply` is triggered by a user click? If a user clicks an element quickly in succession, will this not result in multiple calls being made? – Ali Aug 27 '13 at 19:39
  • Each previous $scope.$apply would have cleared out before the browser accepted the click, so you'll be fine if they're based on user interaction. The only time you would run into trouble would be if you had something running inside an angular $scope.$apply that called $scope.$apply again. If you're running into that, put your actions inside a $timeout() as discussed [here](http://stackoverflow.com/questions/12729122/prevent-error-digest-already-in-progress-when-calling-scope-apply/18996042#18996042). – betaorbust Feb 18 '14 at 18:15