JavaScript / Express error handling w/ promises So I'm wondering how to properly handle errors in JavaScript when utilizing promises. I'm currently throwing errors for everything so that I can break out of the promise - if I can't find something, if there was a missing param, an operation failed, etc.

It seems wrong to be throwing an exception for everything like this, but this is the best thing I've come up with so far after much thought. I am sure to catch all of my thrown errors in the routes which passes them on to my middleware.

Is there a better way?



// SERVICE / MODEL LOGIC
getUserByEmail() {
  if (!this._model.email) {
    throw new VError('Missing email.');
  }

  return UserModel.findOne({ email: this._model.email }).exec()
    .then((result) =&gt; {
      if (!result) {
        throw new VError(errors.NOT_FOUND, 'Could not find user.');
      }

      return result;
    })
    .catch((error) =&gt; {
      throw new VError(error, 'Could not find user.');
    });
}

// ROUTE
router.get('/users/:email', (req, res, next) =&gt; {
  const model = new UserModel({ email: req.params.email });

  res.setHeader('Content-Type', 'application/json');
  return new UserService(model).getUserByEmail()
    .then(result =&gt; res.status(200).send(result))
    .catch(error =&gt; next(error));
});

// MIDDLEWARE
const errorHandling = (error, req, res, next) =&gt; 
  res.status(VError.info(error).status || 500).send(error.message);
There's a big problem here.  getUserByEmail() can either return a promise or throw synchronously which is a bad design and very unfriendly for the caller.  Instead, you want any synchronous errors to be returned as a rejected promise.

The beginning of your code should be changed from this:

// SERVICE / MODEL LOGIC
getUserByEmail() {
  if (!this._model.email) {
    throw new VError('Missing email.');
  }


to this:

// SERVICE / MODEL LOGIC
getUserByEmail() {
  if (!this._model.email) {
    return Promise.reject(new VError('Missing email.'));
  }


The other throw statements are what you do from a .then() handler to turn the promise chain into a rejected promise.  You could also do return Promise.reject(...), but throw works just as well.