处理快速异步中间件中的错误 [英] 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
目前不支持 promises,未来的 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)
如果 promise 被拒绝,则到达 express 错误处理程序并避免 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
这篇关于处理快速异步中间件中的错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!