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

Express错误处理中间件未触发致服务崩溃问题求助

问题原因

你的路由处理器是async函数,内部抛出的错误会转化为未处理的Promise拒绝,Express无法自动将这类错误传递给自定义错误处理中间件,最终导致服务器崩溃。

解决方案

方案一:手动捕获错误并传递给next

修改路由处理器,添加next参数,用try/catch捕获错误后传递给错误中间件:

import express, { Request, Response, NextFunction } from "express";
import { body, validationResult } from "express-validator";

const router = express.Router();

router.post(
    "/lead",
    [
        body("email").isEmail().withMessage("Email must be valid"),
        body("name").notEmpty().withMessage("A name has to be provided"),
    ],
    async (req: Request, res: Response, next: NextFunction) => {
        try {
            const errors = validationResult(req);

            if (!errors.isEmpty()) {
                throw new Error("Invalid Email");
            }

            const { email, name } = req.body;

            console.log("Creating a user...");

            res.send({});
        } catch (err) {
            next(err); // 将错误传递给自定义错误处理中间件
        }
    }
);

export { router as leadRouter };

方案二:封装通用async错误处理包装函数

避免每个async路由都重复写try/catch,可以定义一个通用包装函数自动捕获错误:

import express, { Request, Response, NextFunction } from "express";
import { body, validationResult } from "express-validator";

const router = express.Router();

// 定义async错误处理包装函数
const asyncHandler = (fn: (req: Request, res: Response, next: NextFunction) => Promise<any>) => {
    return (req: Request, res: Response, next: NextFunction) => {
        fn(req, res, next).catch(next);
    };
};

router.post(
    "/lead",
    [
        body("email").isEmail().withMessage("Email must be valid"),
        body("name").notEmpty().withMessage("A name has to be provided"),
    ],
    asyncHandler(async (req: Request, res: Response) => {
        const errors = validationResult(req);

        if (!errors.isEmpty()) {
            throw new Error("Invalid Email");
        }

        const { email, name } = req.body;

        console.log("Creating a user...");

        res.send({});
    })
);

export { router as leadRouter };

方案三:直接返回express-validator验证错误(更贴合场景)

既然已经使用express-validator,可以直接返回验证结果,无需手动抛错:

import express, { Request, Response } from "express";
import { body, validationResult } from "express-validator";

const router = express.Router();

router.post(
    "/lead",
    [
        body("email").isEmail().withMessage("Email must be valid"),
        body("name").notEmpty().withMessage("A name has to be provided"),
    ],
    async (req: Request, res: Response) => {
        const errors = validationResult(req);

        if (!errors.isEmpty()) {
            return res.status(400).send({ 
                message: "Something went wrong",
                details: errors.array() 
            });
        }

        const { email, name } = req.body;

        console.log("Creating a user...");

        res.send({});
    }
);

export { router as leadRouter };
补充说明

Express的错误处理中间件仅能捕获同步代码错误,或通过next(err)主动传递的错误。对于async函数内部的错误,必须手动捕获后传递给next,或通过包装函数自动处理,否则会触发未处理的Promise拒绝,导致服务器崩溃。

内容的提问来源于stack exchange,提问作者Wagner Gauer

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 14:52:57