Stop JavaScript Promises Swallowing Exceptions


It’s very hard to debug a crash when no stack traces are printed. It becomes a case of manually trying to find the error.

GET /foo/bar/
Doing something useful
Error: Expected } near ;

ES6 promises doesn’t seem to offer the functionality to change this, and bluebird has on[Possibly]UnhandledRejection, which can only be used if you don’t add a .catch() case to the promise. There is no global callback for a rejection unless it’s unhandled. To workaround this, we’re going to need to override the method which runs the callbacks. This is a little hacky, and relies on the library not changing - but it’s better than swallowing errors.

First, if you haven’t already, install Bluebird.

npm install --save bluebird

Next, make a file somewhere (perhaps called bluebird.js) with this as its contents:

const Promise = require('bluebird')

// Throw errors in promises rather than calling reject()
// Makes debugging A LOT easier
Promise.prototype._rejectCallback_old = Promise.prototype._rejectCallback
Promise.prototype._rejectCallback =
    function(reason, synchronous, ignoreNonErrorWarnings) {
        if (reason.stack) {
            throw reasong
        } else {
            this._rejectCallback_old(reason, synchronous, ignoreNonErrorWarnings)

module.exports = Promise

Alternatively you could just print reason.stack if it exists, however I prefer a full crash whilst debugging. You could also make it possible for promises to declare whether they should throw errors - similar to the throw keyword in Java - and print out the stack rather than crashing in that case.