Blog

Introduction to async / await with Koa2

Async / Await is one of the most awaited features of Javascript, which is already available under the harmony flag on V8 engine. However there are full fledge Node frameworks already around it. KoaJS2 is one of the upcoming frameworks, created by the the developers who made the very popular Express framework. Since Express has now been sold to Strongloop (which got bought by IBM), there is no word on the new version of Express. But Koa is definitely here already and its super amazing.

Before we move onto Koa2, what is async/await? It is a method of handling asynchronous functions in a synchronous manner. So we can call an async function and then use the `await` keyword which will stop the code from further execution until the result is returned. This is very similar to the ‘then’ of the promises, but instead of passing in a function as a callback everything becomes in line (and awesome). Async functions return promises, so technically you can still use `then` on them as well.

When you start playing around with Koa2 initially, the first thing that strikes you the most is how minimal and Express-like the framework is. The next thing you notice is of course async / await and how nice the code looks. One word of caution though, Koa1 was created around generators initially, however with the introduction of async/await coming next year, they chose to move to to that instead. One of the main reasoning behind it was that async/await also support promises which gives them a slight edge over generators (in every day usage). Thus while browsing most support and documentation, you will find examples with the generators instead of async/await. You can use all those libraries and examples, but you will also need to use koa-convert to convert them into async/await. 

The best way to get started with Koa2 is to use a starter repo – with babel so you don’t need to use any flag with the NodeJS execution. I forked out this awesome repository and added Sequelize to it [https://github.com/recurship/api-koa-sequelize-starter]. Simply run `yarn` (you all use yarn now right?) to install the dependancies and then `yarn dev` to kick off the server. I still need to add the migration tools for Sequelize, however until then passing a param `resetdb=true yarn dev` generates the tables for your datasource. I have also added a sample model, complete with basic tests which can be copied over to create new models (and see some awesome example code)!

So when you dive down into the src folder, you can see an all familiar structure, starting with the all familiar app.js. The routes folder houses the controller and models. For prototypes and MVPs which I am usually working on, fat controllers usually make more sense, so thats how most of the structure is laid out, along with the documentation and testing files.

Starting with the `app.js` file, this is where the server kicks off from. You can see several libraries being imported on top ( all hail imports :bow: ) which include `koa-router` to manage the routes, `koa-body` which manages the request.body parameter. `koa-helmet` has been added for beefing up basic security. `winston` is a very popular library for logging (avoid using console.log, use winston to control the log level and the output streams!). We have added some custom middle wares for error handling and then imported our routes. All code below that just sets things up and kicks of the server!

export async function get(ctx) {
  const demos = await Demo.findAll({});
  ctx.body = demos;
}

Opening the `demo.controller.js` file and you can find several new things here. First one is the `ctx` variable which is now the context of the request rather than separate request, response objects. This context variable has your request details, including the body data and query params, and you also set the response elements to this as well. So a simple `ctx.body = ‘hello world’` will return the text `hello world` in the response. You can set other things like status using their respective properties.

The code mentioned above is an example from the controller file. Even though the code is very short, its using async/await and looks super nice. Demo is the Sequelized model on which we are calling find all to get all the demo objects. And since the findAll call returns a promise, we can simply use it with await! So the rule is that we can use await with functions which are declared as async or promises. This is very useful since we can use them in our current codebases as well without breaking anything.

But what about error handling? Since we can are no longer passing an error callback, or can use the `catch` function on the result, how can we detect a failure. For that we will use our good old try / catch block. So where ever we want to control the error flow simply wrap the async / await code around the try catch block and any failures will end up in the catch block.

And finally what happens when we want to run multiple async tasks, and await for them all at the same time? Simply use Promise.all and you can await on the promise returned by the Promise.all function. So the coolest thing about the async / await is its strong compatibility with promises (too bad the promise cancellation idea got struck off). 

Any questions? Fire away at mashhoodr@recurship.com


Leave a Reply

Your email address will not be published. Required fields are marked *