Server for Node.js
Published in

Server for Node.js

Server’s middleware ♥ Promises

This is the journey of creating a simple and powerful server for Node.js.

I decided to step back and change the way middleware works before committing to 1.0.0. It hasn’t been easy, however I think that we can achieve a lot more with ES6+ than with Connect’s middleware and Koa’s middleware is way too complex for Server’s purpose.


I decided to create a new standard for Server’s middleware:

Synchronous: just a function that gets the context and returns anything.

// Parse the body from the request
const bodyParser = ctx => {
ctx.req.body = parsebody(ctx.req);

Asynchronous: a function that gets the context and returns a promise that will be resolved (or rejected) when the processing finishes.

// Using a Promise-aware library, more and more everyday
const auth = ctx => findUser( => {
ctx.req.user = user;
// Porting an existing callback-based library
const ported = ctx => new Promise((resolve, reject) => {
doSomethingAsync({}, (err, cb) => {
if (err) reject(err);

This was a “what would the best way for creating middleware with ES6 from scratch?” kind of idea. I still needed to check if this makes sense at all.

Joining middleware

For testing I made a function that joins them. I got bitten with express when I tried to do the same (100% my fault for not learning how it worked better) but I was surprised at how easy it was when using promises.

The objective of join is that this code works as expected:

// my-custom-middleware.js
const join = require('./join');
const parseBody = ctx => {
ctx.req.body = bodyparser(ctx.req);
const auth = ctx => findUser(ctx.req.session.user).then(user => {
ctx.req.user = user;
// Return a single middleware that chains them
module.exports = join(parseBody, auth);

This join can be defined with just native code:

// join.js
// Pass a group of middleware and return a single one
module.exports = (...mid) => ctx => mid.reduce((prev, next) => {
// Pass always the original context; not the returned one
return prev.then(next).then(fake => ctx);
// Get it started with the right context
}, Promise.resolve(ctx));

We should totally do loadware(mid).reduce... with loadware to flatten the array, but I didn't want to add this dependency for the example.

That’s it. Now you get a single middleware from those two by just using native code and Promise-aware middleware.

Compatibility with Express/Connect

I also made a function to make any of the original express middleware work with server (making it promise-aware). It is quite easy to use:

// compress.js
const compress = require('compression')({ /* opts */ });
const modern = require('./modern');
module.exports = modern(compress);

To allow for dynamic options is slightly more complex:

// body-parser.js
const compress = require('compression');
const modern = require('./modern');
module.exports = ctx => {
const middleware = compress(ctx.options.compress);
return modern(middleware)(ctx);


The main problem is that a promise chain cannot be stopped in a non-error way so it’s not possible to easily halt the call even when a router has successfully been called.

We are mostly ignoring the return value and I think promises require to be resolved or rejected to avoid memory leaks, so leaving an unsolved promise also doesn’t help.

This leads to the first constrain:

All the routers will be final; only the first router that matches a path will be used and the rest are ignored:

get('/', ctx => { /* called */ }),
get('/', ctx => { /* ignored */ }),
get('/', ctx => { /* ignored */ }),

The second but also important problem is handling errors. All of the middleware accepts a single parameter, ctx, so it cannot be analyzed to see which one is supposed to handle errors.

This leads to the second constrain:

Only throw to the middleware chain when there is a truly catastrophic global issue; try to resolve the local issues within your middleware:

ctx => {
// Recoverable error
// NO: throw new Error('No nnn active. Halt it all!');
// Yes:
ctx.log('No nnn active. To use it make sure ...');


This is still alpha software, but so far every indication is that we can transition to an awesome Promise-aware world while easily bringing all of the ES5-world code. See more about the project in Github.

 by the author.




Journey to launching *server* for Node.js

Recommended from Medium

Top Component Libraries for React Native Web

A Helpful Checklist While Adding Functionality to a React-Redux app

This FAQ will be frequently updated and added to as the vaccine process continues.

Configure your NodeJS Application with IBM Cloud App Configuration using nconf-appconfig

Working with JFreeChart and iTextPDF (PieChart in PDF)

How to Build a Scalable CSS Architecture in React

View of skyscrapers from street level

Developing a Snake Game With JavaScript

Building a Custom Select field without any JavaScript

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Francisco Presencia

Francisco Presencia

Open sourcerer. Love programming and Javascript. ISO 8601 evangelist.

More from Medium

Make Query In Mongodb with the mongoose in node js.

Authentication and Authorization with JWTs in Node && Express.js

Register Insomnia

Beginning with KoaJS and Creating Server using Koa

An Introduction To NodeJS