处理Express异步中间件中的错误 [英] Handling errors in express async middleware
问题描述
我在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屋!