You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Express 异步函数错误处理不生效,触发错误时服务直接崩溃排查

问题原因

  1. 你封装的catchAsync逻辑本身没有问题,仅能捕获Mongoose主动抛出的异常(比如传入的id不符合MongoDB ObjectId格式时的CastError、数据校验失败的ValidationError等)。当你传入的伪造id符合24位十六进制的ObjectId格式但数据库中不存在对应记录时,Campground.findById(id)会返回null,不会抛出异常,因此不会触发捕获逻辑。
  2. 此时代码会继续执行模板渲染逻辑,如果你的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 01:15:01