I love moving electrons
11 Jun, 2018
Filtered Exception Catching with Bluebird Promise

The promise pattern in javascript is a mighty abstraction. Apart from the obvious advantage of writing sequential asynchronous code in less error-prone synchronous manner; it provides inherient error handling. Bluebird's promise library provides potpourri of features including filtered exception catching.

Let's look at a simple promise chain:

checkNetworkConnection()
.then(checkToken)
.then(checkSerialPort)
.catch(function(error){
    log.error(error.message);
});

This is a very neat looking promise chain, however if any of then functions reject or throw exception, the tailing catch is not going know where that happened, unless a switch case is used to check possible error type/code. Bluebird's promise provides a clean mechanism for implementing filtered catch. The catch syntax for filtering looks like this:

.catch(
    class ErrorClass|function(any error)|Object predicate...,
    function(any error) handler
) -> Promise

The first argument is a filter clause which identifies type of error the catch method will handle, this filter clause can be an error class/constructor. Let's define a custom error object:

// ErrorA.js
function ErrorA(message) {
    this.name = "Error A";
    this.code = "ERROR_CODE_A";
    this.message = message;
}
ErrorA.prototype = Object.create(Error.prototype);

module.exports = ErrorA;

Same thing in ES6:

// NetworkConnectionError.js
export default class NetworkConnectionError extends Error{
    constructor(){
        super("Error A");
        this.code = "ERROR_CODE_A";
    }
}
// index.js
import NetworkConnectionError from './NetworkConnectionError';

function checkNetworkConnection(){
    return new Promise(function(resolve, reject){
      reject(new NetworkConnectionError())
  });
}

checkNetworkConnection()
.then(checkServer)
.then(checkSerialPort)
.catch(NetworkConnectionError.check(), function(error){
    log.error(error.message);
})
.catch(function(error){
    log.error(error.message);
});

comments powered by Disqus