表达错误的中间件而没有`next()`?

时间:2019-10-24 07:11:10

标签: node.js express error-handling

我正在使用Express,并且想使用内置的中间件来处理错误。

我正以这种方式使用它-

app.use((err,req,res,next)=> {
    console.log('error');
)};

现在,仅当我在路由器中使用next(error)(其中errorError类型的对象)时,此中间件才可用。 另一方面,如果我只是在路由器中throw new Error(),则不会调用中间件。

有什么办法可以省略next()? 这样,如果我的路由器中抛出任何错误,它将由中间件处理?

2 个答案:

答案 0 :(得分:0)

如果引发是同步的,则可以发明自己的请求处理程序包装器,该包装器将捕获所有异常并将其转换为对next()的调用:

app.get2 = function(path, fn) {
    app.get(path, function(req, res, next) {
        try {
            fn(req, res, next);
        } catch(err) {
            next(err);
        }
    });
};

并且,用法示例:

app.get2("/test", function(req, res, next) {
    throw new Error("testing...");    // will end up in next()
});

然后,如果您的fn函数同步引发,那么它将被您的get2()包装器捕获,并会自动为您调用next(err)

如果异步抛出,则无法正常工作。没有用于异步引发的通用包装器,因为引发异步回调的引发不会投给您的代码-它们会针对您正在使用的任何异步操作返回到异步基础结构中,并且只有它们可以捕获它。如果您仅将诺言用于异步操作,则诺言基础结构将自动捕获您的抛出并将其转变为拒绝的诺言,您可以对返回和拒绝的诺言执行与上述类似的操作。 Koa框架(Express的派生)已经做了类似的事情,我认为Express 5将具有类似的功能。

答案 1 :(得分:0)

如果您可以使用async/await随附的Node.js> = 8,则可以在路由上使用以下包装函数:

const wrap = fn => {
  return async function(req, res, next) {
    let e = null;
    try {
      await fn(req, res, next);
    } catch (err) {
      e = err;
      next(err);
    }

    if (!e) {
      next();
    }
  };
};

    app.get(
      "/path",
      wrap(async (req, res) => {
        // use sync style code here which can throw
      })
    );