处理Express异步中间件中的错误 [英] Handling errors in express async middleware

查看:384
本文介绍了处理Express异步中间件中的错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在Express中有一个async中间件,因为我想在其中使用await来清理我的代码.

I have an async middleware in express, because I want to use await inside it, to clean up my code.

const express = require('express');
const app = express();

app.use(async(req, res, next) => {
    await authenticate(req);
    next();
});

app.get('/route', async(req, res) => {
    const result = await request('http://example.com');
    res.end(result);
});

app.use((err, req, res, next) => {

    console.error(err);

    res
        .status(500)
        .end('error');
})

app.listen(8080);

问题在于,当它拒绝时,它不会转到我的错误中间件,但是如果我删除了中间件中的async关键字和throw,它将删除.

The problem is that when it rejects, it doesn't go to my error middleware, but if I remove the async keyword and throw inside a middleware it does.

app.get('/route', (req, res, next) => {
    throw new Error('Error');
    res.end(result);
});

所以我得到的是UnhandledPromiseRejectionWarning,而不是输入我的错误处理中间件,我如何让错误冒泡并表示处理它?<​​/p>

So I'm getting UnhandledPromiseRejectionWarning instead of entering my error handling middleware, how can I let the error bubble up, and express handle it?

推荐答案

问题是当它拒绝时,不会出现我的错误 中间件,但是如果我删除async关键字并扔进一个 中间件.

The problem is that when it rejects, it doesn't go to my error middleware, but if I remove the async keyword and throw inside a middleware it does.

express当前不支持promise,将来的express@5.x.x

express doesn't support promises currently, support may come in the future release of express@5.x.x

因此,当您传递中间件功能时,express将在try/catch块内调用它.

So when you pass a middleware function, express will call it inside a try/catch block.

Layer.prototype.handle_request = function handle(req, res, next) {
  var fn = this.handle;

  if (fn.length > 3) {
    // not a standard request handler
    return next();
  }

  try {
    fn(req, res, next);
  } catch (err) {
    next(err);
  }
};

问题是try/catch不会在async函数外部捕获Promise拒绝,并且由于express不会向中间件返回的Promise添加.catch处理程序,因此您得到一个UnhandledPromiseRejectionWarning.

The problem is that try/catch won't catch a Promise rejection outside of an async function and since express does not add a .catch handler to the Promise returned by your middleware, you get an UnhandledPromiseRejectionWarning.

最简单的方法是在中间件中添加try/catch,然后调用next(err).

The easy way, is to add try/catch inside your middleware, and call next(err).

app.get('/route', async(req, res, next) => {
    try {
        const result = await request('http://example.com');
        res.end(result);
    } catch(err) {
        next(err);
    }
});

但是,如果您有很多async中间件,则可能有些重复.

But if you have a lot of async middlewares, it may be a little repetitive.

由于我喜欢中间件尽可能干净,并且通常会让错误冒出来,所以我在async中间件周围使用了包装器,如果承诺被拒绝,它将调用next(err),到达快递错误处理程序并避免UnhandledPromiseRejectionWarning

Since I like my middlewares as clean as possible, and I usually let the errors bubble up, I use a wrapper around async middlewares, that will call next(err) if the promise is rejected, reaching the express error handler and avoiding UnhandledPromiseRejectionWarning

const asyncHandler = fn => (req, res, next) => {
    return Promise
        .resolve(fn(req, res, next))
        .catch(next);
};

module.exports = asyncHandler;

现在您可以这样称呼它:

Now you can call it like this:

app.use(asyncHandler(async(req, res, next) => {
    await authenticate(req);
    next();
}));

app.get('/async', asyncHandler(async(req, res) => {
    const result = await request('http://example.com');
    res.end(result);
}));

// Any rejection will go to the error handler


还有一些可以使用的软件包


There are also some packages that can be used

  • async-middleware
  • express-async-handler

这篇关于处理Express异步中间件中的错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆