Enter Koa 2

Frameworks such as Express heavily relied on callbacks to perform asynchronous actions and while it’s possible to write fairly clean and readable code using callbacks not every developer out there will know how or even care about doing so. At first, Koa got rid of the aforementioned callback hell using a combination of Promises and Generators but now that we have the async/await syntax available in Node Current we can make use of it.

Your typical Koa hello-world app looks like this:

const koa = require('koa');

const app = new koa(); app.use(function *(next){

var start = new Date;

yield next;

var ms = new Date - start;

console.log('%s %s - %s', this.method, this.url, ms);

}); app.use(function *(){

this.body = 'Hello World';

});



app.listen(3000);

In contraposition, the Koa 2 version would look something like this:

const koa = require('koa');

const app = new koa(); app.use(async (ctx, next) => {

const start = new Date;

console.log(`Started at: ${start}`);

await next();

const ms = new Date - start;

console.log(`Elapsed: ${ms}ms`);

}); app.use(async (ctx) => {

ctx.body = 'Hello world';

}); app.listen(3000);

Yeah, async/await and Generators are deeply related and might look very similar but Generators are way more generic. Actually, you can implement your own version of async/await with Generators and Promises

Koa Middleware

“Koa middleware are simple functions which return a MiddlewareFunction with signature (ctx, next). When the middleware is run by an "upstream" middleware, it must manually invoke next() to run the "downstream" middleware.” — Koa 2.x Guide

Koa middleware can be implemented using a stack flow which allows us to easily manage request/response flows. Our small middleware here logs the elapsed milliseconds since the request was issued:

app.use(async (ctx, next) => {

const start = new Date;

console.log(`Started at: ${start}`);

await next();

const ms = new Date - start;

console.log(`Elapsed: ${ms}ms`);

});

If you’ve never used Koa you’re probably wondering what the heck is that await next() doing there, in the middle of our code. Well, if that’s the case just think about the two ways of event propagation: capture and bubble. The code before the next() call is analogous to event capturing (capture down) and the code after that corresponds to event bubbling (bubble up). To further illustrate, let’s take a look at the following example:

... app.use(async(ctx, next) => {

// Step 1

const start = new Date;

console.log(`Started at: ${start}`);

await next(); // Step 2

// Step 7

const ms = new Date - start;

console.log(`Elapsed: ${ms}ms`);

}); app.use(async(ctx, next) => {

// Step 3

console.log(`Hey, I'm just another middleware`);

await next(); // Step 4

// Step 6

console.log('More stuff after body has been set');

}); app.use(async(ctx) => {

const name = await dbCall();

// Step 5

ctx.body = `Hello ${name}`;

console.log('Body has been set');

}); ...

The flow goes down like this:

1- Log start date in middleware 1

2- Go to the next middleware, the execution of the next two lines is paused

3- Do stuff in middleware 2

4- Go to the next middleware, the execution of the next line is paused

Once we’ve hit the last middleware the flow continues as follows:

5- Body is set, “bubble” up, since there are no more next() calls

6- Do stuff in middleware 2 after body is set

7- Do stuff in middleware 1 after body is set and Step 6 is done

As you can see the execution goes all the way down and then it goes back all the way up providing a really nice way to create middleware and compose request/response flows with ease.