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

NodeJS Express错误在Angular前端以HTML返回,如何转为JSON?

问题

我搭建了一个用next()捕获错误的Node.js Express服务器,现在遇到个问题:抛出的错误到Angular前端后是HTML格式,想改成JSON格式。

我的控制器示例代码:

function moveTable(req, res, next) {
  const payload = jwtDecode(req.headers.authorization.split(' ')[1]);
  authService.getAuthToken(payload.sub)
      .then(token => cloverOrderService.moveTable(req.body, token.merchantId,token.cloverToken))
      .then(data => res.send(data))
      .catch(err => next(err));
}

server.js中的错误处理器函数:

module.exports = errorHandler;

function errorHandler(err, req, res, next) {
    res.setHeader('Content-Type', 'application/json');
    console.log(JSON.stringify(err));
    if (typeof (err) === 'string') {
        return res.status(400).json({ message: err });
    }

    if (err.name === 'ValidationError') {
        return res.status(400).json({ message: err.message });
    }

    if (err.name === 'UnauthorizedError') {
        return res.status(401).json({ message: 'Invalid Token' });
    }

    return res.status(500).json({ message: err.message });
}

Angular错误拦截器代码:

@Injectable()
export class ErrorInterceptor implements HttpInterceptor {
    constructor(private authenticationService: AuthenticationService) {}

    intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        return next.handle(request).pipe(catchError(err => {
            if (err.status === 401) {
                this.authenticationService.logout();
                location.reload(true);
            }
            
            const error = err.error.message || err.statusText;
            return throwError(error);
        }))
    }
}

前端拦截到的错误格式(JSON结构):

{
  "error": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\">\n<title>Error</title>\n</head>\n<body>\n<pre>Error: Order Already Exists For Table general<br> &nbsp; &nbsp;at Object.moveTable (/Users/shahzibsarfraz/Documents/REPO/Dine-N-Go/clover-server-backend/cloverOrders/cloverOrders.service.js:843:15)<br> &nbsp; &nbsp;at process.processTicksAndRejections (node:internal/process/task_queues:95:5)</pre>\n</body>\n</html>\n",
  "headers": {
    "normalizedNames": {},
    "lazyUpdate": null,
    "lazyInit": "ƒ"
  },
  "message": "Http failure response for http://localhost:4000/api/cloverOrders/moveTable: 500 Internal Server Error",
  "name": "HttpErrorResponse",
  "ok": false,
  "status": 500,
  "statusText": "Internal Server Error",
  "url": "http://localhost:4000/api/cloverOrders/moveTable"
}

可以看到服务器抛出的错误信息在返回JSON的error属性里,但却是HTML格式。我已经尝试在Node端的errorHandler里设置响应头为JSON,但没效果,请问我漏了什么?


解决方案

1. 检查错误处理器的挂载顺序

Express中间件按注册顺序执行,自定义错误处理器必须放在所有路由和其他中间件的最后。如果它被放在路由之前,或者某些中间件(比如静态资源中间件)之后但路由之前,错误抛出时会先触发Express默认的错误处理器,返回HTML格式的错误。

正确的挂载示例:

// 先挂载所有业务路由
app.use('/api', apiRoutes);

// 最后挂载自定义错误处理器
app.use(errorHandler);

2. 确认错误是否进入自定义处理器

在errorHandler开头加一行日志,比如console.log('触发自定义错误处理'),看控制台是否输出。如果没输出,说明错误没传递到这里:

  • 检查cloverOrderService.moveTable内部的错误是否被正确抛出
  • 确认.catch(err => next(err))是否真的捕获到了Promise的拒绝

3. 避免冲突的错误处理逻辑

如果使用了第三方中间件(比如express-validator、morgan等),有些中间件自带错误处理逻辑,可能先于你的处理器返回响应。可以暂时禁用这些中间件,测试是否能正常返回JSON错误。

另外,确保你的错误处理器已经发送响应后,不要调用next()或next(err),否则会触发Express默认错误处理器覆盖你的响应。

4. 处理全局未捕获错误

如果错误发生在Express路由上下文之外(比如全局Promise未捕获、非请求触发的异常),自定义错误处理器无法捕获。需要添加全局错误监听:

// 捕获未处理的Promise拒绝
process.on('unhandledRejection', (err) => {
  console.error('未处理的Promise拒绝:', err);
  // 若涉及HTTP请求,建议在服务层提前捕获这类错误并通过next(err)传递
});

// 捕获未捕获的同步异常
process.on('uncaughtException', (err) => {
  console.error('未捕获的同步异常:', err);
  process.exit(1);
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 21:29:56