koa-compose is the small library which does the composition of middleware generator functions. Its source code is very simple, only 29 sloc. compose is the main method to compose middleware. The argument middleware is an array of middleware generator functions in the order of registration. The return value of compose method is a generator function with argument next. next is an optional generator function which is the last middleware in the chain.

function compose(middleware){
  return function *(next){
    if (!next) next = noop();

    var i = middleware.length;

    while (i--) {
      next = middleware[i].call(this, next);

    return yield *next;

function *noop(){}

Let's go through the generator function code line by line. The first line if (!next) next = noop(); sets next to a do-nothing generator function noop if it's null. i is the loop variable for array middleware starting from the last middleware in the array. In the while loop, the generator function of each middleware is invoked with the current value of next as the argument, the returned generator object is set as the new value of next. Then yield* is used to delegate to final next generator object.

We'll see how middleware are used in the sample application of Koa basics. The middleware array contains two generator functions, log and setBody. In the while loop, generator function setBody is invoked first with the argument next set to noop and next is set to the generator object of setBody. Then generator function log is invoked with the argument next set to the generator object of setBody and next is set to the generator object of log. The last yield* next expression delegates to the generator object of log.

The returned generator function of compose is turned into a regular function that returns a Promise using co.wrap from co. The wrapped function is the actual request handler. When a request comes in, the generator object of log starts execution first and runs until the yield next, so the start time is recorded. next is a generator object of setBody, invoking yield next triggers the execution of setBody and set the response body. Finally, the generator object of log resumes execution and calculate the duration.

results matching ""

    No results matching ""