如何解决Promise中bcrypt.compare配合await使用时的语法报错问题
错误原因
- 你在
.then()的普通回调函数内使用了await,但该回调没有标记async关键字,这是触发await is only valid in async function语法错误的直接原因。 - 此前移除
await后所有密码校验都通过,是因为bcrypt.compare()是异步方法,不加await时返回的是Promise对象,布尔判断中所有对象都为真,所以永远走校验成功分支。 - 你的
pool.query同时传入了空回调函数又调用了.then(),属于冗余写法,部分数据库驱动会因为同时传回调导致Promise不生效,需要先删除这个多余的空回调。
修复方案
方案1:保留Promise.then写法,给回调加async标记
//data connection pool const pool = require('../models/db'); const { handleError, ErrorHandler } = require('../helpers/error'); const bcrypt = require('bcrypt'); module.exports = (req, res) => { const {user_name, password} = req.body; const sql = `SELECT * FROM Govt_profiles WHERE user_name = ?`; // 移除多余的空回调 pool.query(sql, [user_name]) .then(async rows => { // 给then的回调加async关键字 const user = rows.find( user => user['User_Name'] === user_name); if (user == null) { req.session.error = new ErrorHandler(400, 'Cannot find user'); return res.render('login_user', { error: req.session.error }); } try { const isPwdValid = await bcrypt.compare(password, user['Password']); if (isPwdValid) { // 补全session赋值逻辑,否则渲染时会取不到值 req.session.user_name = user['User_Name']; console.log('Password matched, login success'); return res.render('user-progress', { userName: req.session.user_name, attempts: req.session.attempts || 0, grade: req.session.grade || 0 }) } else { // 补全密码不匹配的分支处理 req.session.error = new ErrorHandler(401, 'Incorrect password'); return res.render('login_user', { error: req.session.error }); } } catch(e) { console.log("something broke: ", e); res.status(500).send(); } }) .catch(err => { console.log(err.message); req.session.error = new ErrorHandler(404, 'Incorrect user name'); res.render('login_user', { error: req.session.error }); }) }
方案2:全async/await写法(更推荐,逻辑更清晰无嵌套)
//data connection pool const pool = require('../models/db'); const { handleError, ErrorHandler } = require('../helpers/error'); const bcrypt = require('bcrypt'); // 给整个路由处理函数加async标记 module.exports = async (req, res) => { const {user_name, password} = req.body; const sql = `SELECT * FROM Govt_profiles WHERE user_name = ?`; try { // 直接await获取查询结果 const rows = await pool.query(sql, [user_name]); const user = rows.find( user => user['User_Name'] === user_name); if (user == null) { req.session.error = new ErrorHandler(400, 'Cannot find user'); return res.render('login_user', { error: req.session.error }); } const isPwdValid = await bcrypt.compare(password, user['Password']); if (!isPwdValid) { req.session.error = new ErrorHandler(401, 'Incorrect password'); return res.render('login_user', { error: req.session.error }); } // 校验通过,存session req.session.user_name = user['User_Name']; return res.render('user-progress', { userName: req.session.user_name, attempts: req.session.attempts || 0, grade: req.session.grade || 0 }) } catch(e) { console.log("server error: ", e); req.session.error = new ErrorHandler(500, 'Server internal error'); res.render('login_user', { error: req.session.error }); } }
内容的提问来源于stack exchange,提问作者Daniel Torres
相关产品推荐
相关产品推荐

