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> at Object.moveTable (/Users/shahzibsarfraz/Documents/REPO/Dine-N-Go/clover-server-backend/cloverOrders/cloverOrders.service.js:843:15)<br> 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

