Angular $ scope. $ apply vs $ timeout how safe $ apply

I'm trying to better understand the nuances of using the $ timeout service in Angular as a kind of "safe $ apply method" method. Mostly in scenarios where a piece of code can be executed in response to an Angular event or an event without an angular, such as jQuery or some standard DOM event.

As I understand things:

  • Copy code in $ scope. $ apply works fine for scripts where you are not already in the digest loop (jQuery event), but will throw an error if the digest is running.
  • The cover code in the call to $ timeout () without a delay parameter, does the digest loop already work or not

After looking at the source code of Angular, it looks like this: $ timeout makes a call to $ rootScope. $ apply ().

  • Why doesn't $ timeout () also throw an error if the digest loop is already running?
  • It is best to use $ scope. $ apply (), if you know for sure that the digest will not be executed, and $ timeout (), when is it necessary for security anyway?
  • Is $ timeout () really acceptable "safe", or are there gotchas?

Thank you for understanding.

+61
scope angularjs
Apr 14 '14 at 21:30
source share
3 answers

After looking at the source code of Angular, it looks like this: $ timeout makes a call to $ RootScope. $ Apply ().

  • Why doesn't $ timeout () also throw an error if the digest loop is already running?

$timeout uses the undocumented Angular $browser . In particular, it uses $browser.defer() , which interrupts the execution of your function asynchronously through window.setTimeout(fn, delay) , which will always work outside the Angular life cycle. Only once window.setTimeout launched your function, there will be a $timeout call to $rootScope.$apply() .

  • It is best to use $ scope. $ apply (), if you know for sure that the digest will not be executed, and $ timeout (), when is it necessary for security anyway?

I would say so. Another use case is that sometimes you need to access the $ scope variable, which, as you know, will be initialized after the digest. A simple example could be if you want the state of the form to get dirty inside your controller constructor (for some reason). Without $ timeout, the FormController not initialized and published to $ scope, so wrapping $scope.yourform.setDirty() inside $ timeout ensures that the FormController been initialized. Of course, you can do all this with a directive without $ timeout, just using a different use case.

  • Is $ timeout () really acceptable "safe", or are there gotchas?

It should always be safe, but your approach to the method should always target $ apply (), in my opinion. The current Angular application I'm working on is quite large, and we only had to rely on $ timeout, not $ apply ().

+50
Apr 15 '14 at 3:05
source share

If we use $ apply in the application, we can get already completed Error: $ digest. This is because a single $ digest loop can run at the same time. We can enable it using $ timeout or $ evalAsync.

The $ timeout does not generate an error like "$ digest is already running" because $ timeout tells Angular that after the current wait cycle, wait times are waiting and thus guarantee that no collisions will occur between the digest cycles and therefore the $ exit timeout will run in the new $ digest loop.

I tried to explain them: Comparison of application, timeout, digest and evalAsync .

Maybe this will help you.

+13
Jul 27 '15 at 9:12
source share

As far as I understand, $timeout is a wrapper around setTimeout that implicitly calls $scope.$apply , which means that it runs outside the angular lifecycle but starts the angular lifecycle itself. The only thing I can think of is that if you expect your result to be available for this $digest , you need to find another way to "apply safely" (which, AFAIK, is only available through the $scope.$$phase ) .

+4
Apr 14 '14 at
source share



All Articles