如何在API的Service层抛出错误时指定对应HTTP状态码?
解决方案:自定义错误类实现状态码绑定
当然可以在抛出错误时指定对应的HTTP状态码,不用改动现有分层逻辑,核心是通过自定义错误类给错误附加状态码属性,让Controller层捕获后识别并返回对应响应码。
1. 定义带状态码的自定义错误类
创建继承自原生Error的类,额外添加statusCode属性存储HTTP状态码:
class HttpError extends Error { statusCode: number; constructor(message: string, statusCode: number) { super(message); this.statusCode = statusCode; // 修复原型链,保证instanceof判断正常 Object.setPrototypeOf(this, HttpError.prototype); } }
2. 修改Service层,抛出带状态码的自定义错误
把原有的throw new Error()替换为自定义错误,根据业务场景匹配对应状态码:
export const loginUser = async (email: string, password: string) => { if (!email || !password) { // 字段缺失:400 请求参数错误 throw new HttpError('All fields are required', 400); } const user = await findUser(email); if (!user) { // 用户不存在:404 资源未找到 throw new HttpError('User does not exist', 404); } const isValid = validPassword(password, user.password.salt, user.password.hash); if (isValid) { const { refreshToken, accessToken } = issueJWT(user._id); return { refreshToken, accessToken }; } else { // 密码错误:401 未授权 throw new HttpError('You entered the wrong password', 401); } };
3. 修改Controller层,捕获并处理自定义错误
在catch块中判断错误类型,使用自定义错误的statusCode返回响应,未知错误仍返回500:
export const login = async (req: Request, res: Response) => { const { email, password } = req.body; try { const { accessToken, refreshToken } = await loginUser(email, password); res.cookie('jwt', refreshToken, { httpOnly: true, secure: true }); return res.status(200).json({ accessToken }); } catch (error) { if (error instanceof HttpError) { return res.status(error.statusCode).json({ error: error.message }); } // 其他未知错误返回500 return res.status(500).json({ error: 'Internal server error' }); } };
补充说明
这种方式既保留了Service层(负责业务逻辑和错误定义)与Controller层(负责HTTP响应处理)的职责分离,又能精准返回对应状态码。后续新增错误场景时,只需扩展自定义错误或添加新的状态码映射即可。
内容的提问来源于stack exchange,提问作者user18923197
相关产品推荐
相关产品推荐

