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

使用Express+mysql2实现注册功能时的错误处理及响应异常问题

问题分析与解决方案

核心问题

  1. 重复执行SQL+未捕获回调错误:MemberRepository.signup中同时调用了conn.query(回调式)和conn.execute(Promise式),两次执行插入操作;回调里的错误未被捕获,触发了mysql2 Connection的error事件,而未处理的Connection error会直接导致Node.js进程崩溃。
  2. 错误处理链条断裂:
    • Repository层错误被吞掉,未向上抛出
    • Service层的try/catch强行吞掉错误,未传递给路由层
    • 路由层同时调用next(err)和res.send,逻辑冲突导致响应异常

分步修复

1. 修复MemberRepository:统一用Async-Await处理SQL

去掉冗余的回调式查询,改用Promise形式的execute,正确抛出错误:

const db = require("../config/mysql.js");

class MemberRepository{
    async signup(params){
        const sql = "insert into MEMBER (email,pw,nickname) values(?,?,?)";
        const conn = db.init();
        try{
            const [result] = await conn.execute(sql, params);
            return result;
        }catch(err){
            // 直接抛出错误,让上层处理
            throw err;
        }finally{
            await conn.end();
        }
    }
}

const memberRepository = new MemberRepository;
module.exports = memberRepository;

2. 修复AuthService:不吞掉错误

移除多余的try/catch,让错误自然向上传递:

const memberRepository = require("../repository/memberRepository");
// 其他无关代码保持不变

class AuthService{
    async signup(params){
        // 直接返回Promise,错误自动传递给上层
        return memberRepository.signup(params);
    }
}

const authService = new AuthService();
module.exports = authService;

3. 修复路由层:正确处理响应与错误

不要同时调用next(err)和res.send,统一在catch分支判断错误类型并返回响应:

const express = require("express");
const authService = require("../service/AuthService.js");

const router = express.Router();

router.post('/signup', async function(req, res){ 
    try{
        const body = req.body;
        const params = [body.email, body.password, body.nickname];
        await authService.signup(params);
        // 注册成功返回明确响应
        res.status(200).json({code: 200, message: "注册成功"});
    }catch(err){
        console.log(err);
        // 判断是否为重复邮箱错误
        if(err.code === 'ER_DUP_ENTRY'){
            res.status(400).json({code: 400, message: "邮箱已存在"});
        }else{
            res.status(500).json({code: 500, message: "服务器内部错误"});
        }
    }
})

module.exports = router;

4. 优化全局错误监听(可选)

让全局监听能正确处理未捕获的错误,避免进程崩溃:

process.on('unhandledRejection', (err) => {
    console.error('未处理的Promise拒绝:', err);
});

process.on('uncaughtException', (err) => {
    console.error('未捕获的异常:', err);
    // 可选择优雅退出,避免进程处于不稳定状态
    process.exit(1);
});

关键说明

  • mysql2的Connection对象若触发未处理的error事件,Node.js会直接崩溃,必须确保所有数据库操作的错误都被捕获
  • 异步代码统一用Async-Await/Promise,不要混用回调和Promise,避免错误遗漏
  • 错误处理要形成完整链条,从Repository到Service再到路由,逐层传递或处理,不要随意吞掉错误

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 22:19:50