$q, maybe used it but haven't uncovered some of the awesome features
$q provides such as
$q.race(). This article dives into ES2015 Promise API and how it maps across to
$q for AngularJS. This post is all about
Table of contents
What is a Promise?
A promise is a special type of Object that we can either use, or construct ourselves to handle asynchronous tasks. We deem them promises because we are "promised" a result at a future point in time. For example an HTTP call could complete in
400ms, a promise will execute when resolved.
A promise has three states, pending, resolved or rejected. Using
$q in Angular, we can construct our own promises, however let's look at the ES2015
Promise Object first to get familiar on how to create one.
The main things here are
Promise and the
We simply call
new Promise() and inside can perform an asynchronous task, which may be for wrapping particular DOM events, or even wrapping third-party libraries that are not promise Objects.
For example, wrapping a pseudo third-party library called
myCallbackLib() which gives us a success and error callback, we can construct a Promise around this to
reject where appropriate:
$q implementation in AngularJS is now available in the same aspect as the native ES2015
Promise Object, therefore we can do this:
The only difference here from above is changing
new Promise() to
$q(), simple enough.
Ideally you'd implement this inside a service:
Which would then be injected into a component controller:
When to use $q
At the moment we've only looked at some pseudo-examples, here's my implementation on wrapping the
XMLHttpRequest Object to become a promise-based solution, this kind of thing should be the only real reason(s) you create your own
Please note, this is not advocating the use and creation of the
$http inside Angular, which creates and returns a promise Object for you:
Which means, you do not, and shouldn't ever do this as it's just creating a new promise Object from an existing promise Object:
Golden rule: use
$q for non-promise stuff, that's it! Well, only create your Promises in this case, however you can use other methods such as
$q.race() alongside other promises.
$q.defer() is just another flavour, and the original implementation, of
$q() as a Promise constructor. Let's assume the following code, adapted from the before example using a service:
$q.when() / $q.resolve()
$q.resolve() (they are identical,
$q.resolve() is an alias for
$q.when() to align with ES2015 Promise naming conventions) when you want to immediately resolve a promise from a non-promise Object, for example:
$q.when() is also the same as
$q.reject() will immediately reject a promise, this comes in handy for things such as HTTP Interceptors at the point of no return to return, so we can just return a rejected promise Object:
The time will likely arise where you need to resolve multiple promises at once, this is easily achieved through
$q.all() by passing in either an Array or Object of promises which will call
.then() once both are resolved:
$q.race method is one of the newer arrivals to Angular, and is similar to
$q.all(), however whichever promise resolves first is the only response Object passed back to you. Assume API call 1 and API call 2 are both executed simultaneously, and API call 2 resolves before API 1, you'll only get API call 2 as the response Object. In other words the fastest promise wins and is returned on its own:
$q for constructing promises from non-promise Objects/callbacks, and utilise
$q.race() to work with existing promises.
If you like this article, check out my advanced Angular 1.5 master course which covers all the
ui-router, component architecture and the new
For anything else, the $q documentation.