Master Asynchronous JavaScript in a few simple steps

Posted 01.04.2016 in Technology by Jakob Lundberg

 

Introduction

One of the powerful features of JavaScript is its asynchronous nature. And it is also one of the most difficult to master. But asynchronous JavaScript does not have to be hard.

When programming for the web a lot of functions have to behave asynchronous. If not, our programs would frequently get blocked waiting for some network transmission. Writing asynchronous code can however be quite tricky. This makes many people think that JavaScript is a difficult language. But it is really the problems we use JavaScript to solve that are tricky in the first place. And because JavaScript is so frequently used in an asynchronous manner, there are many tools that can help us.

Today we will have a look at a library that we use at Deductive Labs called Q. And how it can help make asynchronous programming easier.

Promises

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

The problem

Lets start by looking at the most basic problem. We have a function that asynchronously returns a value that we want to access.

https://gist.github.com/jakob-lundberg/19dc06062dffbfff4f7e

This fails as the value is not returned in time from the function.

The solution

To fix this we use the defer function from Q.
https://gist.github.com/jakob-lundberg/8fe9be5e3086e83b1a5f

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

The problem

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
https://gist.github.com/jakob-lundberg/9e1d8fe14cd619dd1d0a9cb829cf843a
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.

The solution

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.

https://gist.github.com/jakob-lundberg/9e2608096d491e0f09ac5de4fe274556

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

The problem

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.

https://gist.github.com/jakob-lundberg/3ee9a6e55fb09c235e72af26199397dc

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.

The solution

Luckily 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.

https://gist.github.com/jakob-lundberg/c40a9da133e0d5c4ea1819e294403eef

This makes it very easy to asynchronously gather lots of data and combine it once it is all collected.

Error handling

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.

https://gist.github.com/jakob-lundberg/0418164a8445d27d9a7a93f695967851

Chaining errors

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.

https://gist.github.com/jakob-lundberg/d3c2a72c2c6279537ff135672f3cfc86

Combined errors

This is also possible when combining promises. If any of the individual promises gets rejected, then the combined promise will also get rejected.

https://gist.github.com/jakob-lundberg/ea93483a637293a30e5d5cf04845cabf

Conclusion

Due to tools like the Q library, asynchronous JavaScript doesn’t have to be difficult. So take advantage of asynchronous functions as much as possible. As shown here it doesn’t have to be hard and it doesn’t have to make your code a mess.

Although we have been using Q with Node.js here. It is also possible to use it in the browser. Just add

<script src="https://cdnjs.cloudflare.com/ajax/libs/q.js/2.0.3/q.min.js"></script>

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 Q.

All examples can be found on Github

Written by Jakob Lundberg

Jakob is a tech focused system designer. With a background in network management, system administration and development he has an interest in the entire stack.

Always looking for new and improved solutions. Never accepting that things have to be complicated.

Related articles

Using True Color in Vim with Tmux

  Color schemes in the terminal At Deductive Labs we love working with the terminal. But setting the color scheme for the terminal has always been kind of tricky. There…

I Encrypt, therefore I Am

In this age of global surveillance and spying, encrypting communications has become the standard. Companies, big and small, are finally taking the necessary steps to encrypt all their traffic traversing…

Riding the Automation Paradigm Shift?

I have been thinking about and experimenting with automation tools quite a bit for the last year, gradually envisioning the business value of infrastructure automation and subsequently trying to evangelize…