Я использую bcrypt 3.0.6. У меня есть следующий код в моем файле Model:
User.prototype.validPassword = async function(password) {
try{
// original code:
// return await bcrypt.compare(password, this.password);
const match = await bcrypt.compare(password, this.password);
console.info(match);
} catch(error) {
console.info(error);
return false;
}
};
и я вызываю его из моего контроллера:
try {
if (!req.body.userName || !req.body.password) throw "Invalid Login"
user = await User.findOne({
where: { userName: req.body.userName }
})
if (!user) throw "Invalid login"
const match = user.validPassword(req.body.password);
// const match = await bcrypt.compare(req.body.password, user.password);
if (!match) throw "Invalid login";
// build token
...
});
} catch(error) {
res.status(500).json({
"msg": "Server Error",
"error": error,
})
}
Когда я его отлаживаю, match становится undefined.
Если я сравниваю в контроллере, он работает так, как ожидалось. Я бы предпочел, чтобы сравнение было в файле модели. Что я здесь делаю неправильно?
Я новичок в коде async/await, но я успешно использовал его для реализации нескольких других методов контроллера в том же проекте.
@jonrsharpe Комментарий показывает мою оригинальную конструкцию. возвращаемое значение было добавлено, чтобы я мог поставить точку останова и увидеть значение, возвращаемое методом сравнения bcrypt.
Вы пробовали ставить await перед вызовом функции?





Насколько я использовал async/await в js и понял это, вы должны вернуть обещание в свой метод validPassword. Поскольку метод использует await, он сам по себе является асинхронным методом, который работает вне нормального потока контроллера.
Поэтому, основываясь на вашем коде, я бы рекомендовал изменить его на что-то похожее на это:
User.prototype.validPassword = function(password) {
return new Promise(async function (resolve, reject) {
try{
// original code:
// return await bcrypt.compare(password, this.password);
const match = await bcrypt.compare(password, this.password);
console.info(match);
resolve(match)
} catch(error) {
console.info(error);
reject();
}
}
};
и контроллер:
try {
if (!req.body.userName || !req.body.password) throw "Invalid Login"
user = await User.findOne({
where: { userName: req.body.userName }
})
if (!user) throw "Invalid login"
try {
const match = await user.validPassword(req.body.password);
If (!match) throw "invalid login";
// build token
} catch (err) {
throw "Server error";
}
...
});
} catch(error) {
res.status(500).json({
"msg": "Server Error",
"error": error,
})
}
В качестве альтернативы вы можете отклонить обещание. Если совпадение ложно, и оценить отклонение в улове.
Я не понимаю, как приведенное выше может указывать на неудачное совпадение пароля. Он потерпит неудачу только в том случае, если выдаст ошибку. Я что-то пропустил?
Извините, я совершенно не понял использование bcrypt.compare и его возвращаемое значение. Ich скорректировал примеры кода.
Если вы видите мое решение ниже, bcrypt.compare уже возвращает обещание, если обратный вызов не предоставлен. Я слишком много думал об этом. Мне просто нужно было вернуть это обещание и await за результат в моем контроллере. Спасибо за честную попытку. Это поставило меня на правильный путь.
Мне потребовалось некоторое время, но я, наконец, смог понять, что я сделал неправильно. Я слишком много использовал async/await. Следующий код работает так, как я ожидал:
User.prototype.validPassword = function(password) {
return bcrypt.compare(password, this.password);
};
Я упустил тот факт (или, точнее, важность того факта), что bcrypt.compare возвращает обещание. Мне просто нужно было вернуть это обещание и await решить его.
И в контроллере:
if (!user) throw "Invalid login";
const match = await user.validPassword(req.body.password);
if (!match) throw "Invalid login";
// build token ...
Несмотря на название
returnValue...