You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决Promise中bcrypt.compare配合await使用时的语法报错问题

错误原因

  1. 你在.then()的普通回调函数内使用了await,但该回调没有标记async关键字,这是触发await is only valid in async function语法错误的直接原因。
  2. 此前移除await后所有密码校验都通过,是因为bcrypt.compare()是异步方法,不加await时返回的是Promise对象,布尔判断中所有对象都为真,所以永远走校验成功分支。
  3. 你的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 10:45:10