Express 异步函数错误处理不生效,触发错误时服务直接崩溃排查
问题原因
- 你封装的
catchAsync逻辑本身没有问题,仅能捕获Mongoose主动抛出的异常(比如传入的id不符合MongoDB ObjectId格式时的CastError、数据校验失败的ValidationError等)。当你传入的伪造id符合24位十六进制的ObjectId格式但数据库中不存在对应记录时,Campground.findById(id)会返回null,不会抛出异常,因此不会触发捕获逻辑。 - 此时代码会继续执行模板渲染逻辑,如果你的
details.ejs模板中直接访问了campground对象的属性,就会因为campground为null抛出运行时错误,进而导致服务崩溃。
解决方案
步骤1:在所有调用findById的路由中增加非空判断
查询到结果为空时手动抛出错误,以/campgrounds/:id路由为例,修改后代码如下:
app.get('/campgrounds/:id',catchAsync(async (req,res,next)=>{ const { id } = req.params; const campground = await Campground.findById(id); // 新增非空判断,查询结果为空时手动抛出错误 if(!campground){ throw new ExpressError('未找到对应营地信息', 404); } res.render('campgrounds/details',{campground}) }))
同理需要给编辑、更新、删除等所有调用findById/findByIdAndUpdate/findByIdAndDelete的路由都加上上述非空判断逻辑。
步骤2:优化错误处理中间件,增加问题排查能力
可以在错误处理中间件中增加错误日志打印和状态码设置,方便定位问题:
app.use((err,req,res,next)=>{ console.error('捕获到错误:', err.stack); const status = err.statusCode || 500; const message = err.message || '服务内部错误'; res.status(status).send(`Error here! 错误信息:${message}`); })
验证逻辑
修改完成后再次测试:
- 访问格式非法的id(如
/campgrounds/123),会触发Mongoose抛出的CastError,被catchAsync捕获后进入错误处理中间件返回错误提示 - 访问格式合法但不存在的id,会触发手动抛出的
ExpressError,同样进入错误处理中间件返回提示,服务不会崩溃
内容的提问来源于stack exchange,提问作者Okta25
相关产品推荐
相关产品推荐

