AngularJS–Part 11, Promises

Introduction

This is a series of posts about AngularJS and our experiences with it while migrating the client of a complex enterprise application from Silverlight to HTML5/CSS/JavaScript using AngularJS as a framework. So far I have published the following posts

The easiest way to write a program is when everything is sequential. We have one command or instruction executed after the other. But in most cases this is not the best way to code, specifically not in an application with a GUI. A user expects the application to remain responsive all the time, no matter what tasks are running. What this means is that the UI should not freeze, windows should be able to redraw themselves when e.g. moved or resized or the mouse pointer should react when we move the mouse, etc. To achieve this goal we structure our code in a way that it can run asynchronously or in a non-blocking way. When creating e.g. a native Windows application we can use multiple threads to achieve this goal. The main thread is used for all graphic operations whilst long running operations (that most often need no or only limited interaction with the UI) can run in so called worker or background threads. On our modern computers, tablets or phones with multi core processors several threads can run truly in parallel without interrupting each other.

But here we are talking about JavaScript code running on the client in the context of a browser. In this scenario we only ever have one single thread available and thus we have to find other means of how to achieve asynchrony.

Callback functions

The way how every JavaScript developer implements his/her first asynchronous code is by using callback functions. If you have ever used jQuery Ajax calls you are certainly very familiar with this coding pattern

Promise

Using callback functions to achieve asynchrony in code becomes just way too complicated when you have to compose multiple asynchronous calls and make decisions depending upon the outcome of this composition. While handling the normal case is still somewhat feasible it starts to become very ugly when you have to provide rock solid exception handling.

Comes the Promise to the rescue! According to Promises/A+

A promise represents the eventual result of an asynchronous operation.

Ok, this is quite a mouth full. What does it mean in layman’s term? A promise is an object with a then method. The then method has two (optional) parameters of type function. The signature of the then method looks like this

image

Both functions, the onSuccess and the onFailure, have one parameter. The onSuccess function is called whenever the asynchronous tasks ends successfully and the onFailure function is called if the tasks fails to execute. For each promise only one of the functions can ever be called. The task either succeeds or it fails; no other outcome is possible.

References

There are some very good references available talking about JavaScript Promises in general or in the context of a specific library in particular.

to name just a few…

Samples

Now after all this theory let’s play with promises and create some samples that hopefully will make things clear. I have to admit that, although I have done a lot of asynchronous programming using all kinds of techniques it took me a while to get my head around promises. I think this is mostly due to the fact that there are hardly any good samples to find that introduce the concept in a didactically sound way. I truly hope that the following samples are doing a better job in this regard.

In Angular we have the $q service that provide deferred and promise implementations. This $q service is heavily inspired by the Q library of Kris Kowal.

Deferred represents a task that will finish in the future. We can get a new deferred object by calling the defer() function on the $q service.

image 

Initially this task is in the status pending. Eventually the task completes successfully or it fails. In the former case the status of deferred will be resolved while in the latter case the status will be rejected. But who decides whether the task succeeds or fails, and how can this be achieved? Good question; the deferred object has two methods for this purpose. The first method resolve(…) is used to signal that the task has succeeded

image

Note that the method has one parameter. Whoever calls the method resolve can pass any type of information which shall be the result of the task. It can be a simple type like a string or a number or a complex object. Thus this is also valid

image

The second method reject(…) is used to signal that the task has failed. The reject method also takes one parameter, the reason of the failure. Again the parameter can be a simple type like a string or a complex type like an Error object.

image

or

image

The deferred object has a property promise which represents the promise of this task. With this promise we can register an on success and an on failure function. Both functions take a single parameter. The on success function gets the value that was provided by the caller of the resolve method while the on failure function gets the value (reason of failure) provided by the caller of the reject function

image

A simple promise

Let’s make a working sample with what we have learned. Create a new Angular application with an index.html file containing the layout and an app.js file containing the logic. The content of the index.html should look like this

image

This is a simple view with a button bound to a test() method defined in the SampleCtrl controller and a checkbox bound to the property fail on the $scope of the controller. When the user clicks the button a deferred object should be created and either succeed or fail depending on the status of the checkbox. In both cases the result is shown in an alert box. Let’s see the code in app.js

image

On line 1 we create a new Angular app and on line 2 we define the SampleCtrl controller. In the controller we define the test function that is called when the user clicks the button on the view. On line 6 we create the deferred object. On line 8 we get hold of the promise object of the deferred. We then define on line 9 through 13 what shall happen if the promise either is resolved or rejected. Line 10 or 12 are not executed immediately since the deferred object is a task that will complete in the future.

On line 15 through 18 we either reject the task or resolve the task depending whether or not the user has checked the checkbox on the view. If the checkbox is not checked the the alert with the text “Success: Cool” is displayed. If the checkbox is checked on the other hand the alert box with the test “Error: sorry” is displayed.

Note although this sample is not an asynchronous sample it still shows the concept of promises.

Chaining promises

The return value of the then function of the promise is again a promise. This allows us to combine or chain asynchronous tasks. We can write

image

With each then method we can register an on-success and an on-failure function. Let’s extend our sample. Add the following snippet to the view right after the first div containing the button and the checkbox

image

Now we need to define the test2 function in the controller which will be executed whenever the user clicks on the button.

image

On line 23 and 24 we define again a deferred object and reference its promise. On line 25 through 32 we register an on-success and an on-failure function. In both methods we set the value of the status2 field to an according value which is the result of a static text and the parameter passed to the function. On line 33 through 37 we have a chained then method where we register again an on-success and an on-failure function. On line 39 through 42 we either resolve or reject the promise depending on whether the user has checked the Fail checkbox or not.

It is important to note that the first on-success function defined on line 25 gets the value ‘Hurray’ injected as defined when resolving the promise. On line 28 we define the return value of the promise which will be injected to the second on-success function defined on line 33. The same is true for the on-failure functions. If we omit to define a return value as on line 28 then the value of the result parameter on line 33 would be undefined.

Without running the application try to determine what message the alert boxes on line 34 and 36 will show.

An asynchronous sample

Up to now everything was synchronous and easy to follow. Now let’s introduce asynchrony into play. The easiest way to achieve this is to use the setTimeout JavaScript function.

image

Here the promise is resolved after a timeout of 1000 milliseconds. This simulates e.g. a server call to load some data which takes about 1 second. As usual we can then use the then method to register on-success and on-failure methods

image

If we run this sample the alert box will show up after a delay of approximately 1 second.

Chaining multiple asynchronous (server-) calls

Imagine having a user id in you application. Now you want to load the details of the staff associated with the user account. One way of doing this is to first load the user details which might contain the id of the associated staff. Once we have this id we can then load the details of this user. In this situation we have to chain two asynchronous tasks. Using callback function this would be a quite complicated undertaken resulting in ugly and difficult to understand code, specifically if we also have to implement a robust exception handling. Using promises on the other hand makes the implementation really simple.

Let’s first add another button to our view which when clicked triggers the loading of the data discussed above. This is the snippet we add to our view.

image

and this is the definition of the loadData function triggered by the button click. We define it in our TestCtrl controller.

image

Here we first load information for the currently logged in user (loadUser on line 64). The return value of this call contains amongst other values the id of the associated staff. Once we have that staff id we load the staff details (loadStaff on line 65). Finally we display the staff details as string in an alert box (line 67). In a real application we would probably use the Angular $http service or the $resource service to make a server call and get the data. In this sample we once again use the setTimeout function to simulate such an asynchronous server call and just return pre-canned data avoiding the need to setup a backend. The loadUser function then looks like this

image

and the loadStaff like this

image

The value that we pass to the resolve function on line 74 will be passed as parameter value to the loadStaff function on line 79.

Awaiting multiple promises running in parallel

Assume having to call different backend services to collect data. The application can only continue once all the data has been successfully collected or if at least one of the server call fails. For maximum performance all tasks shall run in parallel. To await multiple tasks running in parallel the $q service offers us the all function. The all function in turn returns a promise. The promise is fulfilled if all parallel running tasks are fulfilled or the promise fails if at least one of the tasks fails. If we have three asynchronous tasks the code looks like this

image

In this case result is an array of values that resolve from the individual promises.

Conclusion

JavaScript promises are a very powerful concept that make handling of asynchronous tasks a breeze. Using promises multiple distinct asynchronous calls can easily be chained or executed in parallel and awaited. Implementing a robust exception handling is equally easy and straight forward. Using callback functions in asynchronous programming should be avoided in favor of using promises.

Related Articles:

Post Footer automatically generated by Add Post Footer Plugin for wordpress.

About Gabriel Schenker

Gabriel N. Schenker started his career as a physicist. Following his passion and interest in stars and the universe he chose to write his Ph.D. thesis in astrophysics. Soon after this he dedicated all his time to his second passion, writing and architecting software. Gabriel has since been working for over 12 years as an independent consultant, trainer, and mentor mainly on the .NET platform. He is currently working as chief software architect in a mid-size US company based in Austin TX providing software and services to the pharmaceutical industry as well as to many well-known hospitals and universities throughout the US and in many other countries around the world. Gabriel is passionate about software development and tries to make the life of developers easier by providing guidelines and frameworks to reduce friction in the software development process. Gabriel is married and father of four children and during his spare time likes hiking in the mountains, cooking and reading.
This entry was posted in AngularJS, asynchronous, introduction. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • Sumeet

    A very nice explanation on promise ! Thanks for this post . I have searched for so many links when I started with angular js. This is the best I have ever seen. Will you please think of the below scenarios in your future posts?

    1. How to interact between angular js and mongo db ?

    2. Can u please answer my question here http://stackoverflow.com/questions/21622628/use-of-exports-myfunc-angularbootmodule-in-angular-js ?

  • Pingback: Retrieving and Displaying Data with AngularJS and the MEAN Stack: Part II | Programmatic Ponderings

  • Michael Harper

    Very good post, I think I actually understand what javascript promises are for! :)

  • Raman Mittal

    god post ,Thanks for saving my day.

  • http://www.dojosto.com Doug Johnston

    One of the best, most succinct posts on promises I’ve seen. Thanks!

  • michael verdi

    Thanks for a great post. Could you please explain a little bit more on the last example. How does the user object get passed to loadStaff(user)? I see that loadUser() is returning a promise. After it resolves it call loadStaff, but what’s confusing to me is that loadStaff is not taking an arg.

    Thanks

    • Jose Manuel Jimenez

      I think this is the control flow:

      The callback function passed as an argument to the .then() function receives as arguments the values passed to the .resolve() call that triggers the .then() call:
      - The first .resolve() inside loadUser is called with an user object –> it’s passed to the loadStaff callback
      - The second .resolve() inside loadStatff is called with a new staff object –> it’s passed to the last anonymous callback function which ‘alert’ it

  • 世强 汤

    It’s very good ! I have understand the $q and promise .Thanks!

  • eric

    This is one of the best promise tutorial for beginner! However, I wonder if you could make the code editable (can copy & paste) rather than just screen-captured one.

  • Claus

    This is the best explanation of promises I’ve seen yet. Thanks for making the article really easy to follow, I feel that I have a much better grasp on promises now.

  • Navada

    Thanks.
    Could have made the code snippets as text rather than images.

  • http://www.adamwaselnuk.com/ Adam Waselnuk

    This was exactly what I needed. A perfect bridge between some examples of $q that I’ve seen and some blog posts that focussed more on the theory of promises. Thank you!

  • Renan Reis

    Awesome article! Very didactic! You rock! Thank you!

  • Moshe Friedman

    WOW! I felt like thousands light bulbs getting lit up in my head when I read the article.

    I don’t think that $q could have been explained any better than this!

    Thank you so much!!!

    • Gabriel Schenker

      I’m happy to hear that. Promises are a very important concept and will soon be a part of the language (ECMA script 6)