Today I will talk about the Async/Await pattern which will be introduced in ES7 (ECMAScript 7). Before I get to that, to provide context, I use promises for few years now with the amazing bluebird library. With the release of Node.js v6, native promises have appeared through the new features provide by ES6 (like classes, arrow operators, generators, native promises, etc.) enabled by default. So to get familiar with these new concepts I have traveled a bit the web and this is where I discovered Async functions. Unfortunately this feature is not available with the ES6 standard but thanks to babel we can already play with them!
Async Functions
An async
function, as its name implies, is a function that will return an asynchronous result through a promise. The code executed inside the async
block will be run like synch code using the await
keyword.
Now an example to take a look at the syntax:
async function doAsyncOps() {
let value = await asynchronousOperation();
let result = await asynchronousOperation2(value);
return result;
}
let promise = doAsyncOps();
promise.then(result => {
console.log(result)
});
In this example, we create an async
method named doAsyncOps
which calls sequentially an asynchronousOperation
then the asynchronousOperation2
before returning the result
. Here the asynchronousOperation
and asynchronousOperation2
return a promise and thanks to the await
keyword we can wait the result of each methods before continuing the block. The await
does not block the thread (javascript is single-thread, so if we block it the performance will be terrible), it just pause the method execution and wait for a result. At the end, the result
is returned, and the async
function wrapped it into a promise to be used later. If an exception occurred inside the async
method, you will just have a promise that will be rejected.
Before / After
In order to highlight the powerfulness of this new feature take a look at a before/after example code:
function blogPostSummary() {
let summary = "";
return getBlogPosts('http://yannickloriot.com/rss').then(posts => {
return posts.reduce((chain, post) => {
return chain.then(_ => {
return extractContent(post);
})
.then(content => {
summary += content;
});
}, Promise.resolve());
})
.then(_ => {
summary += "end";
})
.catch(err => {
summary += `Error occurred ${err.message}`;
})
.then(_ => {
return summary;
});
}
The blogPostSummary
function aims to summarise the blog post by getting each post, extracting their content to make an individual summary of each post and then concatenate them.
Now let’s see the Async/Await version:
async function blogPostSummary() {
let summary = "";
try {
let posts = await getBlogPosts('http://yannickloriot.com/rss');
for (let post of posts) {
summary += await extractContent(post)
}
summary += "end";
}
catch (err) {
summary += `Error occurred ${err.message}`;
}
return summary;
}
It’s more clear, concise and beautiful, no? With async
functions, you can await
on promises and make your code readable in a sequential way. Thanks to the await
keyword, the code can halt in a non-blocking way, waits for the promise to resolve and returns the value. If the promise is rejected, an error is thrown with the rejection value, so you can deal with it using a try-catch
block or let the async
block catch the error for you.
Conclusion
For me the Async functions are really amazing. It is really easy to understand, it is based over Promises and it allows developers to write more concise code. Thanks to this 2 new keywords our code is clean of all unnecessary brackets and braces. Waiting for the release and the implementation of ES7 you can already enjoy this feature using babel or other transpiler.
And you, do you think the Async function is a good thing?