为何try/catch代码块无法捕获Mongoose抛出的ValidationError?
问题根因
- 你当前的
try/catch仅包裹了new Blog()文档实例化代码,但Mongoose的内置类型转换、Schema校验逻辑默认不会在实例化阶段执行,只有调用异步方法save()持久化文档时,才会触发完整的校验逻辑,你遇到的ValidationError实际是在save()阶段抛出的,位于try块覆盖范围之外,自然无法被捕获。 - 代码中Schema定义处的
canst是书写笔误,需要修正为const,否则会直接触发语法错误。 - 额外注意:
save()是异步Promise方法,如果没有加await等待执行完成,异步抛出的错误同样无法被同步的try/catch捕获,会触发未处理Promise异常。
修改方案
调整代码结构,将save()操作纳入try块覆盖范围,同时正确使用await处理异步逻辑;推荐将字段默认值、校验规则统一定义在Schema层,减少接口层的冗余兜底代码。
修正后的Schema定义
// 修正关键字笔误,将字段类型、默认值、必填规则统一定义在Schema层 const blogSchema = new mongoose.Schema({ title: { type: String, required: true }, author: String, url: String, likes: { type: Number, default: 0 } }) const Blog = mongoose.model('Blog', blogSchema)
修正后的接口处理逻辑
注意路由处理函数需要标记为async,才能使用await处理异步操作:
try { const new_blog = new Blog({ title: request_body.title, author: request_body.author, url: request_body.url, likes: request_body.likes }) // 关键:将save操作放入try块,加await等待校验、持久化流程完成 const savedBlog = await new_blog.save() return response.status(201).json(savedBlog) } catch (err) { return response.status(400).send({ error: err.message }) }
补充:如果需要在实例化阶段就同步触发校验,可以在new完文档后手动调用
new_blog.validateSync(),该方法会同步执行校验逻辑,抛出的错误可以直接被外层的同步try/catch捕获,但常规业务场景下直接捕获save阶段的错误即可满足需求。
修改完成后,当传入title为数组这类非预期类型的值时,save()阶段抛出的类型转换、校验错误就会被catch块正常捕获,返回400状态码和对应错误信息,符合预期效果。
内容的提问来源于stack exchange,提问作者Sebekerga
相关产品推荐
相关产品推荐

