ExpressJS Node用户注册:抛出错误还是返回JSON响应?
Express JSON API 异常处理最佳实践
直接返回JSON vs 抛出错误的适用场景
1. 业务逻辑校验类错误(如参数缺失、用户名已存在)
这类属于预期内的业务错误,直接返回标准化的JSON响应更合适——调用方需要明确的业务提示来引导用户操作(比如提示补全信息、更换用户名)。你的现有写法逻辑没问题,但可以优化响应的HTTP状态码,让语义更清晰:
const register = async (req, res) => { const { username, password } = req.body if (!username || !password) { // 更简洁的空值判断 return res.status(400).json({ success: false, message: '用户名或密码不能为空。', errorCode: 'PARAM_MISSING' // 可选:增加错误码方便前端统一处理 }) } const existingUser = await models.User.findOne({ where: { username } }) if (existingUser) { return res.status(409).json({ success: false, message: '该用户名已被注册。', errorCode: 'USER_EXISTS' }) } // 后续注册逻辑... }
2. 系统级/不可预期的异常(如数据库查询失败、第三方服务调用出错)
这类情况适合抛出错误,再通过Express的全局错误中间件统一捕获处理,避免在每个路由里重复写错误逻辑,同时保证所有错误响应格式一致。
步骤1:定义自定义错误类(可选,但更灵活)
class ApiError extends Error { constructor(statusCode, message, errorCode) { super(message); this.statusCode = statusCode; this.errorCode = errorCode; this.name = 'ApiError'; } }
步骤2:在路由中抛出错误
const register = async (req, res, next) => { // 需添加next参数 const { username, password } = req.body if (!username || !password) { return next(new ApiError(400, '用户名或密码不能为空。', 'PARAM_MISSING')); } try { const existingUser = await models.User.findOne({ where: { username } }); if (existingUser) { return next(new ApiError(409, '该用户名已被注册。', 'USER_EXISTS')); } // 创建用户操作,可能抛出数据库异常 await models.User.create({ username, password }); res.status(201).json({ success: true, message: '注册成功' }); } catch (err) { // 捕获系统异常,抛给全局中间件 next(new ApiError(500, '服务器内部错误', 'SYSTEM_ERROR')); } }
步骤3:添加全局错误处理中间件(需放在所有路由之后)
app.use((err, req, res, next) => { if (err instanceof ApiError) { return res.status(err.statusCode).json({ success: false, message: err.message, errorCode: err.errorCode }); } // 处理未捕获的未知错误 res.status(500).json({ success: false, message: '服务器未知错误', errorCode: 'UNKNOWN_ERROR' }); });
总结
- 业务预期内错误:可以直接返回带状态码的JSON,也推荐用全局中间件统一处理(保持路由代码整洁)。
- 系统级异常:必须抛出错误,由全局中间件统一捕获,避免零散处理,保证响应格式一致。
你的现有写法能满足需求,但如果项目接口较多,全局错误中间件的方式更利于维护。
内容的提问来源于stack exchange,提问作者john doe
相关产品推荐
相关产品推荐

