Deviopath › Node.js

Koa-style compose()

Medium · Middleware

Koa runs middleware as an "onion": each async (ctx, next) => {} can do work, await next() to run the rest of the chain, then do more work on the way back. Write compose(middlewares) that returns a function (ctx) => Promise.

- Calling the composed function runs the first middleware. Its next() runs the second one, and so on. next() returns a promise that resolves when the rest of the chain is finished.

- next() in the last middleware resolves immediately.

- A middleware that does not call next() stops the chain.

- Errors (thrown or rejected) travel back up through the await next() calls, and reject the composed promise if nobody catches them.

- Calling next() twice in the same middleware must reject with Error("next() called multiple times").

The driver runMiddleware(spec) is already written. It builds middlewares from step lists: "next" awaits next(), "try-next" awaits it and logs "caught: <message>" on error, "wait" sleeps a few ms, "throw:<msg>" throws, and any other text is pushed to ctx.log. It returns the log, plus "error: <message>" if the composed promise rejected.

Next: In-Memory Todo REST API