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

NodeJS异步函数VerifyUserByUsernamePassword返回值始终为undefined求助

问题:异步函数返回undefined,调用函数无法获取结果

我是JavaScript(及回调函数)新手,在NodeJS应用中编写了异步函数VerifyUserByUsernamePassword,用于从SQL数据库获取用户数据,该功能正常;随后使用BCrypt验证用户输入密码与存储的appPassword是否匹配,验证也可正常执行。但无论密码匹配成功或失败,向调用函数返回JSON对象时,调用函数中的result始终为undefined,附上异步函数及调用函数代码,寻求解决方法。

原异步函数代码

async function VerifyUserByUsernamePassword(userEmail, password) {

    const sql = require('mssql')
    const { configMSSQL } = require("./db.config.js");

    if (sql) sql.close();

    return await sql.connect(configMSSQL).then(async pool => {

        // Stored procedure
        let output_parameter
        return await pool.request()
            .input('Email', sql.NVarChar, userEmail)
            // .output('output_parameter', sql.Int)
            .execute('API_READ_USER_BY_EMAIL')

    }).then(async result => {
        sql.close();
        // sql = null;
        if (result.recordset.length > 0) {

            const appPassword = result.recordset[0].appPassword;

            bcrypt.compare(password, appPassword, async function (err, result2) {
                if (err) {
                    console.log(err);
                    return ({
                        "message": "failed"
                    })
                }
                if (!result2) {
                    // console.log("result2", result2)
                    return ({
                        "message": "failed"
                    })
                }
                console.log("result2 was True")
                return ({
                    "message": "success",
                    "data": result
                })
            })

        } else {
            console.log("Error retrieving User Records for Login Verification......");
            return ({
                "message": "failed"
            })
        }

    }).catch(err => {
        sql.close();
        // ... error checks
        console.log("Error retrieving User Records for Login Verification", err);
        return ({
            "message": "failed"
        });
    });

}

原调用函数代码

exports.VerifyLogin = async (req, res) => {

    var errors = []

    if (!req.body.email) {
        errors.push("Credentials Missing");
    }
    if (!req.body.password) {
        errors.push("Credentials Missing");
    }

    if (errors.length) {
        res.status(400).json({ "error": errors.join(",") });
        return;
    }

    var email = req.body.email
    var password = req.body.password

    const { VerifyUserByUsernamePassword } = require("../database/mssqldb.js");

    await VerifyUserByUsernamePassword(email, password).then(async result => {

        if (result && result.message === "success") {

            res.json(result.data);

        } else {
            res.json({
                "message": "failed",
                "User Record ": email
            },);
        }

    }).catch(err => {
        console.log(err);

        res.json({
            "message": "error",
            "User Record ": email
        },)
    })

}

问题原因

核心问题是你用了bcrypt.compare的回调版本,回调函数里的return不会作为外层then回调的返回值。处理SQL查询结果的那个then函数,在执行bcrypt.compare后没有返回任何值,导致整个VerifyUserByUsernamePassword函数最终返回undefined。

async/await基于Promise工作,你需要把bcrypt.compare包装成Promise,或者直接用bcrypt提供的Promise版本。


修正后的代码

异步函数(VerifyUserByUsernamePassword)

// 模块引入放在文件顶部,避免重复加载
const sql = require('mssql');
const { configMSSQL } = require("./db.config.js");
const bcrypt = require('bcrypt');

async function VerifyUserByUsernamePassword(userEmail, password) {
    try {
        // 关闭可能存在的旧连接
        if (sql) await sql.close();
        
        // 连接数据库并执行存储过程
        const pool = await sql.connect(configMSSQL);
        const result = await pool.request()
            .input('Email', sql.NVarChar, userEmail)
            .execute('API_READ_USER_BY_EMAIL');
        
        await sql.close();

        if (result.recordset.length > 0) {
            const appPassword = result.recordset[0].appPassword;
            // 使用bcrypt.compare的Promise版本,配合await获取结果
            const isPasswordMatch = await bcrypt.compare(password, appPassword);
            
            if (!isPasswordMatch) {
                return { "message": "failed" };
            }
            return {
                "message": "success",
                "data": result
            };
        } else {
            console.log("Error retrieving User Records for Login Verification......");
            return { "message": "failed" };
        }
    } catch (err) {
        // 出错时确保关闭连接
        if (sql) await sql.close();
        console.log("Error retrieving User Records for Login Verification", err);
        return { "message": "failed" };
    }
}

调用函数(VerifyLogin)

统一用async/await风格,避免混合.then()让逻辑更清晰:

const { VerifyUserByUsernamePassword } = require("../database/mssqldb.js");

exports.VerifyLogin = async (req, res) => {
    const errors = [];

    if (!req.body.email || !req.body.password) {
        errors.push("Credentials Missing");
    }

    if (errors.length) {
        return res.status(400).json({ "error": errors.join(",") });
    }

    const { email, password } = req.body;

    try {
        const result = await VerifyUserByUsernamePassword(email, password);
        
        if (result && result.message === "success") {
            res.json(result.data);
        } else {
            res.json({
                "message": "failed",
                "User Record": email
            });
        }
    } catch (err) {
        console.log(err);
        res.json({
            "message": "error",
            "User Record": email
        });
    }
}

额外优化点

  • 模块引入放在文件顶部,避免函数内重复加载,提升性能且减少潜在问题。
  • 尽量统一async/await和.then()的使用风格,优先用async/await让代码更易读。
  • 数据库连接关闭逻辑放在try/catch中,确保无论成功失败都能释放连接资源。

内容的提问来源于stack exchange,提问作者Jan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 17:15:20