简体   繁体   中英

Node JS promise chaining

I am trying to chain a few promises in Node.js, but am only used to jQuery promises. The problem I am having is my higher level function (registerUser) that chains the promises does not seem to fail (go in to the catch handler) when the bcrypt hash fails (I change the code to set the string to null as a test).

What I want to accomplish is

  1. A hash function that returns a promise, and logs its own failure

  2. An insert function that returns a promise, and logs its own failure

  3. A register function that calls the hash, then the insert, and logs either failures

This is my code.

hashPassword(password){
    let self = this;
    // if you set password to null, the catch err is printed.
    // but in registerUser, .then() is still called...
    return bcrypt.hash(password, 10)
        .then(function(hash) {
            return hash;
        })
        .catch(function(err){
            self.logger.error('failed to hash password');
        });
}

insertUser(email, passwordHash){
    let self = this;
    let data = {
        email: email,
        password: passwordHash
    };
    return this.collection.insertOne(data)
        .then(function(res) {
            self.logger.info(`user ${email} registered`);
        })
        .catch(function(err){
            self.logger.error('failed to add user to db');
        });
}

registerUser(email, password){
    let self = this;
    return this.hashPassword(password)
        .then(function(hash){
            // is this returning the promise of 
            // insertUser to the caller of registerUser?
            return self.insertUser(email, hash);
        })
        // which promise am i catching here?
        .catch(function(){
            self.logger.error('failed to register user');
        });
}

Finally someone calls the register function and should know if it was successful.

let user = new User();
user.registerUser('a@b.com', '1234')
   .then(function(){
       res.sendStatus(200);
   })
   .catch(function(){
      res.sendStatus(400);
   });

I think I've realized I was expecting then to be a success handler, but it is also an error handler. This kinda sucks. Is there a success only handler?

catch deals with errors, so if you catch an error in doesn't propagate down the line. If you want that error to continue to a catch block further down you need to return a rejected promise from catch . Something like:

hashPassword(password){
    let self = this;
    // if you set password to null, the catch err is printed.
    // but in registerUser, .then() is still called...
    return bcrypt.hash(password, 10)
        .then(function(hash) {
            return hash;
        })
        .catch(function(err){
            self.logger.error('failed to hash password');
            // Pass on the error
            return Promise.reject('failed to hash password')
        });
}

You'll need to do this for any catch for which you only want side effects, but don't want to actually "catch" the error.

Create the function so they return promises

    createHash(email, password){
        let self = this;
        return this.hashPassword(password);            
    }

First create the hash and use then on the returned promise, In the then handler return create user and return another promise and use another then on it to send the response after the creation of the user. If any error occur the catch will fire returning 400.

    let user = new User();
    user.createHash('a@b.com', '1234')
      .then(function(hash){
          return self.insertUser(email, hash);              
      })
      .then((user) => res.sendStatus(200))
      .catch(function(error){
         res.sendStatus(400);
      });

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM