$apply and thread safety

276 views
Skip to first unread message

matej...@gmail.com

unread,
Dec 5, 2012, 5:47:05 AM12/5/12
to ang...@googlegroups.com
From doc:
$apply() is used to execute an expression in angular from outside of the angular framework. (For example from browser DOM events, setTimeout, XHR or third party libraries).

But $apply assumes, that no other call to $apply is in progress. How one can be sure, that asynchronous events like XHR, etc would not be triggered when other  call $apply is in progress?

J.

Peter Bacon Darwin

unread,
Dec 5, 2012, 6:33:55 AM12/5/12
to ang...@googlegroups.com
Event handlers triggered by asynchronous browser events (i.e. user interactions, such as button clicks, XHR callbacks, and setTimeout callbacks) are always outside of AngularJS and so always need to be wrapped in a $apply.
The only time you may have a problem is if you are using a 3rd party library that provides callbacks (Facebook API, for example).  In this case there is a chance that they sometime call their callbacks asynchronously and sometimes synchronously.
In the case of FB, there is an authentication method, I think, that calls the callback synchronously if there is a clientside error, otherwise passes the callback onto XHR which will call it asynch otherwise.  Only in these cases do you need to worry.  The easiest solution is to ensure the callbacks are always asynch by wrapping them in a $timeout(callback, 0) call.

Pete


--
You received this message because you are subscribed to the Google Groups "AngularJS" group.
To post to this group, send email to ang...@googlegroups.com.
To unsubscribe from this group, send email to angular+u...@googlegroups.com.
Visit this group at http://groups.google.com/group/angular?hl=en-US.
 
 

Jozef Matejička

unread,
Dec 5, 2012, 6:56:49 AM12/5/12
to ang...@googlegroups.com
Thanks Pete for your practical answer.

Let me restate my theoretical question.

Is there guarantee that calling $apply from asynchronous event cannot result in "throw Error($rootScope.$$phase + ' already in progress');" ?

And why?

J.

Peter Bacon Darwin

unread,
Dec 5, 2012, 7:30:39 AM12/5/12
to ang...@googlegroups.com
You can guarantee that all built-in AngularJS event handlers and services will always be inside a $apply call.
You can guarantee that pure browser callbacks are never inside a $apply call.
Other than that you are at the whim of the 3rd party library.

Let me put it to you this way. Is there any guarantee that this code will not throw an error when called?

function divide(a, b) {
 if (b==0) {
    throw new Error('Cannot divide by zero!');
 }
 return a/b;
}




J.

--

Jozef Matejička

unread,
Dec 5, 2012, 8:52:34 AM12/5/12
to ang...@googlegroups.com
Oh my English sucks!


You can guarantee that pure browser callbacks are never inside a $apply call.

How is that possible?

Thanks for your patience!

J.

Peter Bacon Darwin

unread,
Dec 5, 2012, 9:03:54 AM12/5/12
to ang...@googlegroups.com
If you are getting an event directly from the browser then the call stack will look something like this:

browser event loop
-> handle event
    -> call your callback
      -> your callback

AngularJS doesn't get a look in.

Inside the AngularJS $http service you have something more like:

browser event loop
-> handle event
    -> call $http callback
      -> $apply
        -> call your callback
          -> your callback



--

Jozef Matejička

unread,
Dec 5, 2012, 10:53:41 AM12/5/12
to ang...@googlegroups.com
According to this post:
http://stackoverflow.com/a/2734311/482745

It is possible, that two events could fire in same time.
Reply all
Reply to author
Forward
0 new messages