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

如何用中间件处理Express路由错误?为何子路由报错致服务崩溃?

Express子路由异步函数错误未被全局错误中间件捕获的问题

我用Node.js和Express搭建服务器时遇到问题:全局错误处理中间件能处理根路由的同步错误,但子路由异步函数中抛出的错误无法被处理,直接导致服务器崩溃。我不想用try/catch,因为这违背错误处理中间件的设计初衷,请问这是为什么?

相关代码

Server.js

import SubRouter from './routes/SubRouter.js';
import express from 'express';

const server = express();
server.use(express.json())
server.use('/sub', SubRouter);

server.get("/update", (req, res) => { 
    throw new Error("Testing") // 此处错误不会导致服务器崩溃
});

// 全局错误处理中间件
server.use((err, req, res, next) => {
    console.error("Error Handled")

    res.json({
        error: err.message
    })
})

server.listen(3000, () => {
    console.log(`listening at 3000 ...`);
});

./routes/SubRouter.js

import { Router } from "express";

const SubRouter = Router()

SubRouter.get("/update", async (req, res) => { 

    throw new Error("Testing") // 此处错误会导致服务器崩溃

});

export default SubRouter

错误日志

file:///.../routes/SubRouter.js:7
    throw new Error("Testing") // This crashes the server
          ^

Error: Testing
    at file:///.../routes/SubRouter.js:7:11
    at Layer.handle [as handle_request] (/.../node_modules/express/lib/router/layer.js:95:5)
    at next (/.../node_modules/express/lib/router/route.js:144:13)
    at Route.dispatch (/.../node_modules/express/lib/router/route.js:114:3)
    at Layer.handle [as handle_request] (/.../node_modules/express/lib/router/layer.js:95:5)
    at /.../node_modules/express/lib/router/index.js:284:15
    at Function.process_params (/.../node_modules/express/lib/router/index.js:346:12)
    at next (/.../node_modules/express/lib/router/index.js:280:10)
    at Function.handle (/.../node_modules/express/lib/router/index.js:175:3)
    at router (/.../node_modules/express/lib/router/index.js:47:12)

问题原因

核心原因是:Express 4及以下版本不会自动捕获异步函数(标记了async)中抛出的错误。

  • 根路由的处理函数是同步函数,Express会自动捕获同步抛出的错误,并调用next(err)把错误传递给全局错误处理中间件,因此不会崩溃。
  • 子路由的处理函数是async异步函数,抛出的错误会被包装成Promise的reject状态。Express 4及以下默认不会处理未被捕获的Promise rejection,这会触发Node.js的未捕获异常,进而导致服务器崩溃。

解决方法

方法1:使用异步错误捕获包装函数

写一个通用的包装函数,自动捕获异步函数的错误并传递给next:

// 工具函数:捕获异步路由函数的错误
const asyncHandler = (fn) => (req, res, next) => {
  Promise.resolve(fn(req, res, next)).catch(next);
};

然后在子路由中使用该包装函数:

SubRouter.get("/update", asyncHandler(async (req, res) => { 
    throw new Error("Testing");
}));

方法2:升级到Express 5

Express 5版本已经修复了这个问题,会自动捕获异步路由处理函数中抛出的错误,并传递给全局错误处理中间件,无需额外编写包装函数或try/catch。


内容的提问来源于stack exchange,提问作者Manas R. Makde

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 06:25:36