Search code examples
node.jspromisebluebird

Replacing bluebird with node.js native promises breaks Promise.reject


The following code works perfectly fine when I use bluebird promises:

import * as Promise from 'bluebird';

getAccount(id) {
    var account = find(accounts, ['id', id]);
    return account ?
        Promise.resolve(account) :
        Promise.reject(new NotFoundError());
}

NotFoundError is defined as follows:

export function NotFoundError(message = 'Not Found') {
    this.name = 'NotFoundError';
    this.message = message;
    this.stack = (new Error()).stack;
}
NotFoundError.prototype = Object.create(Error.prototype);
NotFoundError.prototype.constructor = NotFoundError;

However, if I remove the import of bluebird in getAccount() and let node.js take over promises, the code fails inside the NotFoundError() constructor because this is not defined. Specifically, the constructor is called twice, once correctly from the getAccount() code shown above and a second time by node.js's _tickCallback() function with this as undefined:

NotFoundError (errors.js:13)
runMicrotasksCallback (internal/proces…ext_tick.js:58)
_combinedTickCallback (internal/proces…ext_tick.js:67)
_tickCallback (internal/proces…ext_tick.js:98)

Why is node.js calling the NotFoundError() constructor a second time and that too incorrectly!!!

Please help.


Solution

  • The issue is caused by this line:

    .catch(NotFoundError, function() { ... })
    

    Native promises don't have an option to pass a specific error class to a catch method, so what happens is that when an error occurs, NotFoundError is called (without a new in front of it) because it's presumed to be the catch handler.