Break promise chain - stop the next 'then' from executing

Viewed 7630

I am writing a registration system in Node/Express and I am trying to make use of Promises.

The issue is that I get an error message when using them:

Error:

(node:64725) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 2):

Is there a way to stop at a then?

auth.isRegistered(email)
.then((registered) => {
    if ( !registered ) {
        req.flash('pleaseRegister', 'Looks like you haven\'t registered. Please register first.');
        req.session.user = user;
        res.redirect('/register')
    }
})
.then(() => {
    return auth.isVerified(email);
})
.then((verified) => {
    if ( !verified ) {
        console.log('please verify');
        res.redirect('/register/verify');
    } else {
        req.login(user, err => {
            if ( err ) return next(err);
            req.session.timestamp = Date.now();
            auth.updateLastLogin(email)
            .then(() => {
                res.redirect(req.session.returnTo || '/account');
            });
        });
    }
});
3 Answers

You can do the following:

  1. Throw a custom error, when you want to break the promise chain.
  2. Check in catch callback that thrown error is a custom error. If so, just continue, otherwise call next with error object:

Example:

let getBreackChainError = () => {
  let err = new Error();
  err.name = 'BreackChainError';
  return err;
};

auth
  .isRegistered(email)
  .then(registered => {
      if (!registered) {
        req.flash('pleaseRegister', 'Looks like you haven\'t registered. Please register first.');
        req.session.user = user;
        res.redirect('/register');
        throw getBreackChainError();
      }
      return auth.isVerified(email);
  })
  .then(verified => {
      if (!verified) {
        console.log('please verify');
        res.redirect('/register/verify');
        throw getBreackChainError();
      }
      return new Promise((resolve, reject) => {
        req.login(user, err => {
          if (err) {
            return reject(err);
          }
          req.session.timestamp = Date.now();
          resolve();
        });
      });
  })
  .then(() => auth.updateLastLogin(email))
  .then(() => res.redirect(req.session.returnTo || '/account');
  .catch(err => {
    if (err.name !== 'BreackChainError') {
      next(err);
    }
  });

Note. You shouldn't mix callbacks with promises, use something one. In the example above, I promisified req.login, so now it returns a promise.

Language: JavaScript

For simplicity just use:- (in case you don't want to further process the error)

throw new Error("An error occured");

Example:- (fetch)

fetch("endpoint/resource", requestOptions)
        .then(response => {
            if(response != null && response.status == 404) {
                throw new Error("RECEIVED NULL OBJECT");
            }
            return response;
        })
        .then(approvedResponse => approvedResponse.blob())
.catch(e => console.log(e));

UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 2): I believe this is because you do not have a way to handle the error in your initial .thens, because of this you get the above error. Its not "stopping" the .then, but handling the error correctly. you could do (err)=> {return} which would essentially "stop" it but its flow control in your application.

Related