Usually an asynchronous function returns a value when finished. What we can do instead is to return a Promise right away. A promise is a placeholder that will later become resolved with the value. Or rejected if something goes wrong.
Reading the value returned by an asynchronous function
Lets start by looking at the most basic problem. We have a function that asynchronously returns a value that we want to access.
This fails as the value is not returned in time from the function.
To fix this we use the
defer function from Q.
Now the function does not return the value, which is not available right away. Instead we use
defer to create a promise and that can be returned right away. When we get our value we can use this to resolve the promise.
The promise that is returned has a
then method. By using this method we can define the promise fulfillment handler. The fulfillment handler is the first argument of the
then method and is called when the promise is resolved. And it will be called with the value that was resolved.
Thus in the fulfillment handler we can access the value returned from the asynchronous function.
Chaining the asynchronous functions
In this case we want to pass the result from one asynchronous function into another asynchronous function. We first try to do it like this
But this will obviously not work. What we have to do first is wait for the first function to finish. And then send the value into the next one. And then wait for that one to finish. If we where to solve this using something like callbacks we would get nested function upon nested function. This makes it difficult to read and follow the code.
But fortunately it is possible to chain
then methods. This is done by having the first fulfillment handler return a promise from the next function in the chain.
Here we can see the fulfillment handler of the first promise returning the promise from the
addData function. And on this promise we use the
then method to define the second fulfillment handler.
Combining asynchronous functions
Sometimes we have asynchronous functions, but we don’t want to chain them. We want to combine them. For example, we could be getting data from 2 separate sources. And then we want to add these data together.
We could solve this by again using chaining. But that would mean that we would wait for the first data before we fetch the second. And the whole point of doing this asynchronously is that we don’t have to wait, but can run multiple queries at the same time.
Q has a method that can combine promises. The
all method takes an array of promises and returns a combined promise. This promise will not resolve until all the promises in the array have been resolved. And the resolved value will be an array with the individual promises values.
This makes it very easy to asynchronously gather lots of data and combine it once it is all collected.
Sometimes functions are not able to return the value we are asking for. This is especially true when accessing data over the web. Therefore it is important that we are able to handle these situations correctly. And promises can help us with this as well. As mentioned earlier a promise can not only be resolved, it can also be rejected. To catch these rejected promises our
then method allows us to define rejection handlers. When a promise gets rejected it is possible to specify a reason. The rejection handler will then be called with this value.
With a long chain of promises it would get very verbose if we had to write a rejection handler for every promise. But fortunately a rejection will automatically propagate through the chain. Making it possible to just create one final rejection handler that takes care of any rejection that occurs in the chain.
This is also possible when combining promises. If any of the individual promises gets rejected, then the combined promise will also get rejected.
Due to tools like the
Although we have been using
Q with Node.js here. It is also possible to use it in the browser. Just add
and you are good to go.
Q is quite flexible as is can work together with promises from for example jQuery. And learning how to use
Q is also useful for working with AngularJS, as the
$q service in AngularJS is inspired by
All examples can be found on Github