Promises with Express

Error handling with callbacks can become unmanageable the large the codebase. Promises allow errors to be handled in much the same way as traditional exceptions. This can greatly improve code running in Express. To illustrate let’s look at a traditional Express handler.

router.route(‘/customers/:id’)
.get(function(req, res) {
customers.getCustomer(req.params.id, function(err, data) {
if (err) {
res.status(500);
res.json({ error: 'there was an error' });
} else {
res.status(200);
res.json(data);
}
});
});

customers = {
getCustomer: function(customerId, callback) {
customersDb.get(customerId, function(err, data) {
if (err) return callback(err);
callback(err, translateCustomer(data));
});
    }
};
customersDb = {
get: function(id, callback) {
query(id, callback);
}
};

While this is a simple example and is fairly straight forward, imagine a much larger system with additional layers of functionality. At every level errors need to be accounted for and managed. Using promises (with Bluebird), this can be simplified to the following.

router.route(‘/customers/:id’)
.get(function(req, res) {
customers.getCustomer(req.params.id)
.then(function(data) {
res.status(200);
res.json(data);
})
.catch(function(err) {
res.status(500);
res.json({ error: 'there was an error' });
});
});
});
customers = {
getCustomer(customerId, callback) {
return customersDb.get(customerId)
.then(function(data) {
return translateCustomer(data);
});
}
};
customersDb = {
get: function(id) {
return query(id);
}
};

This does not shrink the code that much, but it does show that in a larger system how the elimination of callbacks using promises can allow the bubbling up of errors all the way to the top level without the need to manage them at each level. This becomes even simpler once Express supports Promises.