Fastify中如何实现错误处理:自定义报错结构及抛错方法差异
Fastify错误处理常见问题解答
如何修改默认错误消息的返回结构?
Fastify默认返回的错误结构固定包含statusCode、error、message三个字段,要修改这个结构,直接注册全局错误钩子setErrorHandler即可,这个钩子会捕获Fastify生命周期内所有的路由错误、schema校验错误、插件加载错误等,优先级最高。
示例代码:
fastify.setErrorHandler((error, request, reply) => { // 构造自定义返回结构 const resp = { code: error.statusCode || 500, msg: error.message, data: null, requestId: request.id // 可按需追加业务字段 } // 开发环境可追加堆栈信息方便排查,生产环境关闭 if (process.env.NODE_ENV === 'development') { resp.stack = error.stack } reply.code(error.statusCode || 500).send(resp) })
自定义response schema是用于修改响应结构还是仅做校验?
仅用于响应校验和序列化优化,不会主动修改你实际返回的响应结构:
- 第一层作用是校验:你实际返回的响应内容如果不符合schema定义,Fastify会自动抛出500错误;
- 第二层作用是性能优化:Fastify会根据schema预编译序列化函数,比原生
JSON.stringify效率高2-3倍,大幅提升接口响应速度; - 如果需要响应结构匹配schema定义,需要你在业务代码或者错误处理钩子中主动构造对应结构,schema不会自动做结构转换。
直接抛出Error对象和调用reply相关方法抛错有什么区别?
两种方式最终都会被全局错误钩子处理,返回结果没有本质差异,核心区别仅在适用场景:
- 直接
throw new Error()仅能在同步代码、async/await风格的异步代码中使用,回调风格的异步场景下无法直接抛出; reply.send(new Error())或者@fastify/sensible插件提供的reply.badRequest()、reply.notFound()等方法,所有场景都适用,且内置方法会自动给错误绑定对应HTTP状态码,不需要手动给Error对象挂载statusCode属性,写法更简洁。
通用处理建议
- 所有错误统一走全局
setErrorHandler处理,不要在每个路由单独写错误返回逻辑,保证全项目错误结构一致; - 封装自定义业务错误类,例如
class BizError extends Error,内置业务错误码、HTTP状态码属性,抛业务错误时直接抛出BizError实例,在错误钩子中可以区分系统错误和业务错误做差异化处理; - 优先用async/await写法,业务代码中直接抛自定义错误即可,仅回调场景用
reply.send传错误; - 生产环境禁止返回错误堆栈信息,避免泄露代码敏感信息;
- 响应schema建议和自定义的返回结构对齐,既可以避免校验报错,也能享受序列化性能提升。
内容的提问来源于stack exchange,提问作者TechEmperor95
相关产品推荐
相关产品推荐

