Koa is based on generators which are a new feature in ES6. The syntax for a generator is function* fnName() {}
where fnName
is optional, just as with normal functions. What generators allow one to do is effectively to suspend execution and hand over the execution flow to the calling function, which can then inject data into the generator. This is exploited to make async calls seem sync. Example:
function *() {
var data = yield db.find(); //yield suspends execution and hands over the control flow
data.map(someMapper);
}
As you can see we can pretend the async function db.find
is sync, because the caller takes care of executing the function for us and can inject the response into the variable data. That's the high level overview of generators. How they actually work is another story but nothing you need to worry about at first. ES6 (also known as Harmony) features are not enabled by default so when running node, use the harmony flag: node --harmony index.js
The next important concept in koa is middleware. Koa is a very minimal web framework where everything is its own separate module. There it has no file server, no router, no http method parser (GET
, PUT
, ...). However this gives you freedom to swap pieces to your needs. To compose ones own framework you use a concept called middleware, which is exactly what the name suggests, functions/generators that go between the request and your code. To use a middleware invoke app.use(...)
passing the middleware to the function. When writing request handlers/routes in koa you will end up using some routing middleware like koa-trie-router
. This will allow you to type koa.get('/api', function* (){ ... })
however this is just syntactic sugar for app.use(get('/api', function* (){}))
. So everything is middleware!
The last concept that can be a bit hard to grasp is this
in context of middleware. Koa overwrites this
to be a combination of the request
and response
streams you know from core http
. The rule of thumb is, if you read a variable like this.body
you're reading the request
body, but if you write to this.body = ...
you're writing the the response
body. If this is too complicated or implicit, you can be more verbose by using this.req.body
and this.res.body
respectively.
Now kick-off-koa should be manageable.