U2U Blog

for developers and other creative minds

AngularJS: Async Callbacks and the Angular Execution Context

I was playing around with a Angular and Google Maps, and suddenly the world fell apart. Ok, maybe I'm a bit dramatic here, but angular behaved quite a bit different than I expected.

This is a simplified version of the code that cracked the foundations of my beloved planet:

$scope.geoCode = function () {

  $scope.geocoder.geocode({ 'address': $scope.data.search }, function (results, status) {
    var loc = results[0].geometry.location;
    $scope.data.search = results[0].formatted_address;
    $scope.data.location = { lat: loc.lat(), lon: loc.lng() };
  });
};

This piece of code is part of a controller, when clicking a button it searches for a address and a geolocation based upon the search query.

Now the surprising thing here is that I had to press that button twice to make it work. And here's why: only code that executes in the Angular Execution Context is being watched. Angular does dirty checking to inform the watchers (the ones that call $watch) that something has changed, so the watcher can do things like re-render, re-calculate, etc.

We can explicitly enter the Angular Execution Context(AEC) by calling $apply(fn), but most of the time this is not necessary since Angular calls that behind the scene for us. And this is what's causing the problem. Angular executes the code in my controller in the AEC, but the asynchronous callback is not, and Angular remains unaware of any changes.

We have found the poison, but we also have the remedy, right? Just call $apply!

$scope.geoCode = function () {

  $scope.geocoder.geocode({ 'address': $scope.data.search }, function (results, status) {
    var loc = results[0].geometry.location;
    $scope.data.search = results[0].formatted_address;
    $scope.data.location = { lat: loc.lat(), lon: loc.lng() };
    $scope.$apply("data.location");
  });
}; 

Super! except that now, it works half of the time. And the other half, well..., it sends me this little message:

image

It seems that the $digest loop was still ongoing and you can not call $apply as long as it is running. How long the $digest loop takes is unpredictable. As unpredictable like world-shaking earthquakes! When a model’s value changes, the watchers may respond with even more changes. The $digest loops continues until the model(s) stabilize. For more information about $digest click here.

Hold on! I'm probably not the first guy to ever use an async callback in a controller, what about web service calls for example. Well what about them? Here is an example:

$http.get(url).
  success(function (data) {
    $scope.model.country = data.geonames[0].countryName;
  }).
  error(function (data, status) {
    $scope.model.country = 'server answered with: ' + status;
  });

And this always works. Apparently these callbacks are always called in the AEC without the risk of a re-entry of the $apply. Let's dive into the library itself, and see how it's done.

After scuba diving through the internals of angular for a while I found this little gem:

if (!$rootScope.$$phase) $rootScope.$apply();

It seems that this $$phase flag can hold on of three values, either '$apply', '$digest' or undefined. If undefined, the digest loop has already stopped and we can safely call $apply(). If the digest loop is still ongoing, then my added change to the scope will cause a de-stabilization in the model, and the current digest phase will process my change.

Here is an updated version of my code:

$scope.geoCode = function () {

  $scope.geocoder.geocode({ 'address': $scope.data.search }, function (results, status) {
    var loc = results[0].geometry.location;
    $scope.data.search = results[0].formatted_address;
    $scope.data.location = { lat: loc.lat(), lon: loc.lng() };
    if (!$scope.$$phase) $scope.$apply("data.location");
  });
};

And guess what, it works!

The rumbling sound of colliding rocks grow silent and all is well. Until I suddenly realized that this might not be the best solution ever. $$phase is nowhere to be found in the documentation, and there might be a good reason for that. Also going into the internals of a library is kind of against the rules of encapsulation. Angular might decide to change its internals. As long as the API stays the same, nothing can prevent them. (except for an earthquake, that can stop anything)

So, one final attempt:

$scope.geoCode = function () {

  $scope.geocoder.geocode({ 'address': $scope.data.search }, function (results, status) {

    $timeout(function () {
      var loc = results[0].geometry.location;
      $scope.data.search = results[0].formatted_address;
      $scope.data.location = { lat: loc.lat(), lon: loc.lng() };
    });

  });
};

Basically I'm high jacking the $timeout service. The callback always executes nicely in the AEC and I don't have to get into the guts of Angular.

The only problem with this last one is that it might not be clear to another developer why someone would wrap this callback into a $timeout call. It's just something that you have to know.

Well now you know, and knowing is half the battle. If you want to learn more about AngularJS check out our course.

Here is something to look at while letting it sink:

quake

Comments (53) -

  • Energency Locksmith

    6/17/2015 7:44:13 AM | Reply

    Allstate Locksmith has 24/7 locksmith service for residential, commercial and automotive lock smith needs. From lock outs to rekey and update hardware, call All State

  • backlinks software

    6/18/2015 2:11:04 PM | Reply

    Famous! This is merely incredible! Not merely top quality, however likewise valuable details. And that is uncommon ahead by nowadays! I have to state that I am truly satisfied and will definitely come back once more if you maintain the quality and worth of the material at this degree, or perhaps acquire it on the following degree. All the best, from the bottom of my heart, thanks for your time! God bless!

  • aids

    6/25/2015 4:11:26 PM | Reply

    Great, im into all kinds of free porno

  • high pr backlinks dofollow

    6/26/2015 2:32:54 AM | Reply

    Insightful! Fascinating! Quality! Belongings! Legendary! Terrific! Remarkable! Just all the good words apply to this material! If you keep up the good job, thank you from the bottom of my heart and also heart as well as I will come visit once more!

  • high pr backlinks dofollow

    6/26/2015 5:11:44 AM | Reply

    Remarkable! Simply all the great words use to this content! Thank you from the base of my heart and also soul and I will certainly come see once more if you maintain up the excellent work!

  • blog

    6/28/2015 6:12:28 PM | Reply

    You should take part in a contest for one of the best blogs on the web. I will recommend this site!

  • rollover Gold 401K

    6/28/2015 9:26:47 PM | Reply

    Very good write-up. I certainly appreciate this website. Stick with it!

  • m88 indonesia

    7/1/2015 11:24:14 PM | Reply

    Can I just say what a relief to find someone who actually knows what theyre talking about on the internet. You definitely know how to bring an issue to light and make it important. More people need to read this and understand this side of the story. I cant believe youre not more popular because you definitely have the gift.

  • buy high pr backlinks

    7/6/2015 4:40:01 AM | Reply

    Merely remarkable! I recognize you have put a lot of effort into this and also I wanted to tell you exactly how grateful I am! Hope you placed out even more incredible things in the close to future as well as I will certainly come back and also read it!

  • high pr backlinks dofollow

    7/6/2015 9:06:04 AM | Reply

    Spectacular! Just all the wonderful words use to this content! Thank you from the base of my heart as well as spirit as well as I will come visit once again if you keep up the excellent job!

  • web links

    7/12/2015 9:14:40 PM | Reply

    Your place is valueble for me. Thanks!…

  • click reference

    7/20/2015 2:51:04 AM | Reply

    I simply want to mention I'm newbie to blogging and site-building and definitely loved your blog site. Likely I’m likely to bookmark your blog post . You certainly come with superb stories. Thanks for sharing with us your webpage.

  • Energency Locksmith

    8/4/2015 7:21:57 AM | Reply

    Allstate Locksmith has 24/7 locksmith service for residential, commercial and automotive lock smith needs. From lock outs to rekey and update hardware, call All State

  • important site

    8/12/2015 5:34:07 PM | Reply

    I simply want to tell you that I am new to blogs and truly loved this web blog. Likely I’m likely to bookmark your site . You actually come with fabulous articles and reviews. Thanks a lot for sharing your website page.

  • web index

    8/12/2015 5:50:35 PM | Reply

    You should take part in a contest for one of the best blogs on the web. I will recommend this site!

  • Desmond Ault

    8/15/2015 2:01:34 AM | Reply

    It’s exhausting to search out knowledgeable individuals on this topic, but you sound like you recognize what you’re speaking about! Thanks

  • web index

    8/25/2015 12:29:19 AM | Reply

    This really answered my problem, thank you!

  • Energency Locksmith

    8/26/2015 3:38:09 PM | Reply

    Allstate Locksmith has 24/7 locksmith service for residential, commercial and automotive lock smith needs. From lock outs to rekey and update hardware, call All State

  • web directory

    9/6/2015 2:59:01 PM | Reply

    There are some interesting points in time in this article but I don’t know if I see all of them center to heart. There is some validity but I will take hold opinion until I look into it further. Good article , thanks and we want more! Added to FeedBurner as well

  • canbar büyüsü

    9/7/2015 7:04:08 PM | Reply

    I discovered your blog site on google and check a few of your early posts. Continue to keep up the very good operate. I just additional up your RSS feed to my MSN News Reader. Seeking forward to reading more from you later on!…

  • spor bahisleri

    9/16/2015 8:16:29 AM | Reply

    Hello! I just would like to give a huge thumbs up for the great info you have here on this post. I will be coming back to your blog for more soon.

  • Vashti Trometter

    9/20/2015 10:43:47 AM | Reply

    This weblog is very preternatural, just what i am currently looking for to study on my time out. Thank You

  • Energency Locksmith

    9/25/2015 8:58:54 AM | Reply

    Allstate Locksmith has 24/7 locksmith service for residential, commercial and automotive lock smith needs. From lock outs to rekey and update hardware, call All State

  • young adult

    9/26/2015 10:49:29 PM | Reply

    This web site is really a walk-through for all of the info you wanted about this and didn’t know who to ask. Glimpse here, and you’ll definitely discover it.

  • directory

    9/30/2015 10:59:35 AM | Reply

    I was very pleased to find this web-site.I wanted to thanks for your time for this wonderful read!! I definitely enjoying every little bit of it and I have you bookmarked to check out new stuff you blog post.

  • Energency Locksmith

    10/1/2015 11:13:00 AM | Reply

    Allstate Locksmith has 24/7 locksmith service for residential, commercial and automotive lock smith needs. From lock outs to rekey and update hardware, call All State

  • cosmetic brisbane

    10/2/2015 6:02:38 PM | Reply

    Your place is valueble for me. Thanks!…

  • reference

    10/9/2015 12:46:26 PM | Reply

    I simply want to say I am newbie to blogging and truly loved you're web blog. Most likely I’m planning to bookmark your website . You absolutely have wonderful well written articles. Many thanks for revealing your website page.

  • seo links

    10/15/2015 12:06:51 PM | Reply

    This is the right blog for anyone who wants to find out about this topic. You realize so much its almost hard to argue with you (not that I actually would want…HaHa). You definitely put a new spin on a topic thats been written about for years. Great stuff, just great!

  • seo directory

    10/21/2015 3:22:03 PM | Reply

    Nice post. I learn something more challenging on different blogs everyday. It will always be stimulating to read content from other writers and practice a little something from their store. I’d prefer to use some with the content on my blog whether you don’t mind. Natually I’ll give you a link on your web blog. Thanks for sharing.

  • web index

    11/3/2015 10:41:55 PM | Reply

    Can I just say what a relief to find someone who actually knows what theyre talking about on the internet. You definitely know how to bring an issue to light and make it important. More people need to read this and understand this side of the story. I cant believe youre not more popular because you definitely have the gift.

  • Motion Effects

    11/7/2015 1:03:01 PM | Reply

    Would you be interested in exchanging links?

  • M88

    11/12/2015 5:15:55 AM | Reply

    Spot on with this write-up, I truly think this website needs much more consideration. I’ll probably be again to read much more, thanks for that info.

  • internet directory

    11/21/2015 2:56:22 AM | Reply

    I’d have to check with you here. Which is not something I usually do! I enjoy reading a post that will make people think. Also, thanks for allowing me to comment!

  • sick

    11/24/2015 2:43:12 AM | Reply

    Can I just say what a relief to find someone who actually knows what theyre talking about on the internet. You definitely know how to bring an issue to light and make it important. More people need to read this and understand this side of the story. I cant believe youre not more popular because you definitely have the gift.

  • Real Instagram Followers

    12/12/2015 4:29:37 PM | Reply

    An impressive share, I just given this onto a colleague who was doing a little analysis on this. And he in fact bought me breakfast because I found it for him.. smile. So let me reword that: Thnx for the treat! But yeah Thnkx for spending the time to discuss this, I feel strongly about it and love reading more on this topic. If possible, as you become expertise, would you mind updating your blog with more details? It is highly helpful for me. Big thumb up for this blog post!

  • Krypto500

    12/29/2015 3:56:55 AM | Reply

    You made some decent points there. I looked on the internet for the issue and found most individuals will go along with with your website.

  • y35WHM

    1/5/2016 1:14:18 PM | Reply

    928316 950024Register a domain, search for available domains, renew and transfer domains, and decide on from a wide variety of domain extensions. 377686

  • great site

    1/25/2016 3:12:25 PM | Reply

    I simply want to say I am very new to blogging and certainly loved this blog site. Likely I’m likely to bookmark your blog . You definitely come with perfect well written articles. Thanks for sharing with us your blog site.

Loading