Express中全局异常处理

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并且处理异常,感觉非常的冗余

// 冗余的router
router.all("/test1", async(req, res) => {
    try{
       // ...处理一些事务
       // ...各种 await
       res.end(
           // 成功返回内容
       );
    }catch(err){
        // 此处希望throw err 让server接收并处理,但是会报错
        res.end(
           // 失败返回内容
       );
    }
});
// ...之后还有很多router都要try/catch依次处理异常
=、=
阅读 14.7k
3 个回答

async 函数返回一个 Promise 对象,这个函数中抛出的异常需要通过 Promise 对象的 catch()then() 的第 2 个参数来处理。

当然如想外层函数用了 await,就不是用 catch()then() 来处理了,而是像同步调用那样用 try ... catch ... 来处理。

我的印象中 Express 本身是不支持 Promise/yield/async/await 的(不知道新版本是否发展了相关的支持)。现在一般用对 Promise/yield/async/await 支持得比较好的 Koa。

process.on('unhandledRejection', processErrorHandler);

新手上路,请多包涵

express的app.js在设置中间件去捕获异常了,底层原理ES7的异步async/await,async/await是对ES6 promise的一个封装。
node捕获异常一般三种
uncaughtExpection
回调函数前try-catch(注意措辞,回调函数前)
express框架包起来

如果是回调函数中捕获异常怎么做?用domain去捕获,domian捕获会抛出500错误,但是domain捕获有一个问题,会丢失栈信息,无法保证程序健康进行,所以要结束进程,在回调函数中process.exit(1),然后用node的server.close方法再去释放,server.close连接释放后自动结束进程,所以不用在server.close中去结束进程process.exit(1)
uncaughtExpection捕获异常的的原理就是:uncaughtExpection事件存在回调函数process.on("uncaughtExpection",callback)时node不会强制结束进程,这样可弥补domain丢失stack的问题
所以domian去捕获绝大部分回调函数中的异常,uncaughtExpection去捕获丢失stack异常,这样就完整了

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏