Javascript

TypeScript 2.1 released – Introduction to async / await

Async / await keywords are available in TypeScript since 1.7 version. Until new realease, they were transpiled to generator functions using yield. In 2.1, async and wait are finally downleveling to ES3 and ES5, so now, we could use those features in compatibility with browsers.

Callback Hell

JavaScript is an incredible powerful language. Through its events loop and non-blocking I/O nature, we could easily build asynchronous applications. In the past, to achieve events-based structure, we were using callbacks. Sometimes our code looks like below:


setTimeout(function() {
    console.log('First');
    setTimeout(function() {
        console.log('Second');
        setTimeout(function() {
            console.log('Third');
            setTimeout(function() {
                console.log('Fourth');
            }, 500);
        }, 1000);
    }, 500);
}, 1000);

It is a callback hell. Probably, if our code would be more complex, trying to understand it for another person will looks like this:

cat-gif

It wasn’t a good solution. They are a lot of ways to deal with it. The most common are Promises.

What is Promise?

Promise is just an object that represents a task. It might finish right now or in a little while. We could interact with „task” by passing a callback to its then function. Let’s rewrite our previous example using Promises and arrow functions.


const resolver = (msg, timeout) => new Promise((resolve) => {
    console.log(msg);
    setTimeout(resolve, timeout);
});
resolver('First', 500)
    .then(() => resolver('Second', 500))
    .then(() => resolver('Third', 1000))
    .then(() => resolver('Fourth', 500));

Looks simplier – same result.

Async / await

Async and await keywords are well-known in C# community. They allows us to write asynchronous code in more synchronous way. Let’s rewrite our example again using those features.


const resolver = (msg, timeout) => new Promise((resolve) => {
    console.log(msg);
    setTimeout(resolve, timeout);
});
async function run() {
    await resolver('First', 1000);
    await resolver('Second', 500);
    await resolver('Third', 1000);
    await resolver('Fourth', 500);
}
run();

It also do the same stuff. The simplest explanation of how it works is that await takes a Promise and waits until task is finished. If method has at least one await keyword, it has to have async keyword before function declaration. That’s all.

Full example available on GitHub.