проблема преобразования обратного вызова в обещание - PullRequest
0 голосов
/ 05 декабря 2018

Я новичок, пытающийся понять node.js.Я попытался преобразовать обратный вызов в обещание в своей локальной стратегии для паспорта, после преобразования в обещание у меня возникла ошибка при попытке войти, в которой говорится, что «пользователь не определен».Я уверен, что сделал что-то не так в преобразовании моей функции обратного вызова, не могли бы вы взглянуть на мой код и объяснить, где я сделал неправильно.

вот предыдущий обратный вызов

exports.newLocalStrategy= new localStrategy(
(username,password,done)=>{
  User.find({username: username},(err, user)=>{
    if (err) throw err;
    if(user.length == 0){
      console.log("Unknown User");
      return done(null,false,{message: 'unknown User'});

    }
    comparePassword(password,user[0].password, (err,isMatch)=>{
      if (err) throw err;
      if (isMatch){

        return done(null, user);
        return res.send("Loggedin");

      }else{
        console.log('invalid password');
        return done(null, false, {message:"Invalid password"});
      }
    })
  });
});
const comparePassword = (candidatePassword, hash, callback)=>{
    bcrypt.compare(candidatePassword, hash, (err, isMatch)=>{
        if (err) return callback(err);
        callback(null, isMatch);
      });
}

и код после того, как я превратил его в обещание:

 exports.newLocalStrategy= new localStrategy(
  (username,password,done)=>{
    //promise
    User.find({username: username})
      .then(user =>{
        if(user.length ==0){
          return done(null, false,{message: 'unknown user'})
        }
      })
      .catch(err => {return done(null,err)})
    comparePassword(password,user[0].password)
      .then(isMatch => {
        if (isMatch) return (done,null);
      })
      .catch(err=>{return done(null,err)})
});
const comparePassword = (candidatePassword, hash, callback)=>{
  return new Promise((resolve,reject)=>{
    bcrypt.compare(candidatePassword, hash, (err, isMatch)=>{
      if (err) return reject(err);
      resolve(null, isMatch);
    });
  })
}

Я получаю ошибку в comparePassword(password,user[0].password) этой строке

1 Ответ

0 голосов
/ 05 декабря 2018

Здесь есть два основных вопроса.Поскольку кажется, что вы хотите продолжить делать newLocalStrategy принимать обратный вызов done, я предполагаю, что вы не хотите, чтобы он возвращал обещание, а просто используете обещания внутри.

exports.newLocalStrategy = new localStrategy(
  (username, password, done) => {
    User.find({
        username: username
      })
      .then(user => {
        if (user.length == 0) {
          return done(null, false, { message: 'unknown user' })
        }
      })
      .catch(err => {
        return done(null, err)
      })

    // this is in the wrong scope, `user` is not defined here
    comparePassword(password, user[0].password)
      .then(isMatch => {
        if (isMatch) return (done, null);
      })
      .catch(err => {
        return done(null, err)
      })
  });

const comparePassword = (candidatePassword, hash, callback) => {
  return new Promise((resolve, reject) => {
    bcrypt.compare(candidatePassword, hash, (err, isMatch) => {
      if (err) return reject(err);
      // resolve takes only one parameter
      resolve(null, isMatch);
    });
  })
}

После внесения исправлений это должно выглядеть следующим образом:

exports.newLocalStrategy = new localStrategy((username, password, done) => {
  User.find({ username }).then(users => {
    if (users.length === 0) {
      throw new Error('unknown user');
    } else {
      return Promise.all([users, comparePassword(password, users[0].password)]);
    }
  }).then(([users, isMatch]) => {
    if (isMatch) done(null, users);
    else throw new Error('invalid password');
  }).catch(err => {
    done(null, false, err)
  });
});

const comparePassword = (candidatePassword, hash) => {
  return new Promise((resolve, reject) => {
    bcrypt.compare(candidatePassword, hash, (err, isMatch) => {
      if (err) reject(err);
      else resolve(isMatch);
    });
  });
};

Наиболее запутанной частью этого, вероятно, является строка

return Promise.all([users, comparePassword(password, users[0].password)]);

Это можно было бы упростить до

return comparePassword(password, users[0].password);

, если users не нужно было передавать на следующий .then(), так как он передается на done(), если есть совпадение.Promise.all() принимает массив обещаний и разрешает их перед вызовом следующего обратного вызова .then().users не является обещанием, но оно неявно преобразуется в одно с внутренним значением Promise.resolve() и передается вместе со значением, разрешенным из comparePassword().

. Для дальнейшего использования вы можетеопределили comparePassword(), используя util.promisify():

const comparePassword = require('util').promisify(bcrypt.compare);
...