问题描述
1、如下server配置来捕获路由的异常是否正确?server.js
const express = require('express');const app = express();// ...加载中间件// ...配置路由// 异常处理// 如果是开发环境,则打印异常到控制台if (app.get('env') === 'development') { app.use((err, req, res, next) => { console.error('Error',err); next(err); });}// 如果是非开发环境,则向页面输出错误信息app.use((err, req, res, next) => { res.status(err.status || 500); res.render('error', { message: err.message, error: {} });});app.listen(3000);
2、下面是一个路由对象,在没有promise(async/await)的情况下会正常抛出异常,并在server中捕获xxxRouter.js
const router = require('express').Router();router.all('/test/error', (req, res) => { throw new Error('我就是异常!!!');});
但是在promise(async/await)的情况下则会在控制台报错,server中捕获无法捕获导致q超时
(node:30875) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: 我就是异常!!!(node:30875) DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
xxxRouter.js
const router = require('express').Router();router.all('/test/error', async(req, res) => { throw new Error('我就是异常!!!');});
3、实际使用时每一个路由都要try/catch并且处理异常,感觉非常的冗余
// 冗余的routerrouter.all('/test1', async(req, res) => { try{ // ...处理一些事务 // ...各种 await res.end( // 成功返回内容 ); }catch(err){// 此处希望throw err 让server接收并处理,但是会报错res.end( // 失败返回内容 ); }});// ...之后还有很多router都要try/catch依次处理异常=、=
问题解答
回答1:async 函数返回一个 Promise 对象,这个函数中抛出的异常需要通过 Promise 对象的 catch() 或 then() 的第 2 个参数来处理。
当然如想外层函数用了 await,就不是用 catch() 或 then() 来处理了,而是像同步调用那样用 try ... catch ... 来处理。
我的印象中 Express 本身是不支持 Promise/yield/async/await 的(不知道新版本是否发展了相关的支持)。现在一般用对 Promise/yield/async/await 支持得比较好的 Koa。
回答2:process.on(’unhandledRejection’, processErrorHandler);