Jonny
Jonny

Reputation: 882

Bluebird OperationalError not caught in catch()

The code below uses promises to perform a user registration (Node/Express). I use Mailgun to validate the email address, returning a promise, and inside the promise it will throw an exception if the email address is not valid.

However, when the email address is invalid, and validate_email throws its exception, the catch block in app.post never catches the exception, and Node crashes. What am I doing wrong?

NodeJS v6.9.2; Express v4.15; Bluebird v3.4.7.

(ps I'm creating Bluebird OperationalErrors simply because I've tried custom Error types to throw/catch, and have not gotten it to work, I know I'm kludging it...)

routes.js:

const Promise = require('bluebird');       

router.post('/register', function(req, res, next) {
  console.log('registering... ', req.body); 
  var ret = {};
  
  verifyRecaptcha(req.body.recaptcha)
  .then(()=>{
    // exceptions thrown here do NOT get caught in catch()
    return mail.validate_email(req.body.email);
    
  }).then(() => {
    return db.create_customer(req.body);
    
  }).then((customerId) => {
    ret.status = true;
    ret.customerId = customerId;
    res.send(ret);

  }).error((e)=> { 
    // I expected my validate_email exception 
    // to be caught here, but it isn't
    console.error('/register got an error (108)', e);
    res.status(500).send({
      error: 'unable to register'
    });
    
  }).catch(function(e) {
    console.error('/register got an error (114)', e);
    res.status(500).send({
      error: 'unknown internal error'
    });
  });                                                        
});                                                           

mail.js:

const Promise = require('bluebird');       

var mailgun_validate = require('mailgun-validate-email')(<pubkey...>);

exports.validate_email = function(email) {
  console.log('validate_email', email);
  return Promise.delay(1500).then(()=> {
    mailgun_validate(email, (err, result)=> {
      console.log('-> cb', err, result);
      if (err) throw err; // this gets thrown...
      else if (result && result.is_valid === true) return true;
      else throw errors.newOperationalError('invalid email address', {email:email});
    });
  });
};

errors.js:

const Promise = require('bluebird');       

exports.newOperationalError = function(message, data) {
  var e = new Promise.OperationalError(message);
  for (i in data) {
    e[i] = data[i];   
  }
  return e;
}

Upvotes: 0

Views: 527

Answers (1)

paqash
paqash

Reputation: 2314

You're having this issue because mailgun_validate does not return a promise, thus breaking the promise error handling pattern you have.

You should promisify it in order for the then.then.then.catch chain to work

Upvotes: 1

Related Questions