如何优雅地处理express中的拒绝承诺
我有以下快速控制器如何优雅地处理express中的拒绝承诺,express,promise,es6-promise,express-router,Express,Promise,Es6 Promise,Express Router,我有以下快速控制器 class ThingsController { static async index(req, res, next) { try { const things = await Thing.all(); res.json(things); } catch(err) { next(err); } } } 和路由器 router.route('/things').get(ThingsController.
class ThingsController {
static async index(req, res, next) {
try {
const things = await Thing.all();
res.json(things);
} catch(err) {
next(err);
}
}
}
和路由器
router.route('/things').get(ThingsController.index)
在我的应用程序中,我计划使用几个控制器来呈现结果
我不想每次都重复try/catch块
我的第一个解决方案是将此逻辑提取到句柄承诺拒绝函数中:
const handlePromiseRejection = (handler) =>
async (req, res, next) => {
try{
await handler(req, res, next);
} catch(err) {
next(err);
};
};
现在我们可以从ThingsController.index中删除try/catch块,并需要将路由器更改为:
router.route('/things')
.get(handlePromiseRejection(ThingsController.index))
但是在每一条路线上添加遥控器可能是一项乏味的任务,我希望有更聪明的解决方案
你有什么想法吗?所以,如果你真的想处理每一条路线,这就是你处理拒绝承诺的方式
这里还有一个单行ES6版本
代码
尽管如您所问,最简单的方法是在index.js或app.js上使用,在进程上收听未处理的弹出
process.on("unhandledRejection", (error, promise) => {
console.log("Unhandled Rejection at:", promise, "reason:", reason);
// Application specific logging, throwing an error, or other logic here
});
从处理路由中的异步/等待
错误的正常方法是捕获错误并将其传递给捕获所有
错误处理程序:
app.use(async (req, res) => {
try {
const user = await someAction();
} catch (err) {
// pass to error handler
next(err)
}
});
app.use((err, req, res, next) => {
// handle error here
console.error(err);
});
使用express async errors
包,您可以简单地抛出
(或者不必担心从某个函数抛出的错误
)。来自文档:它没有修补express Router上的所有方法,而是将层#handle属性包装在一个地方,保留express guts的所有其余部分。
用法很简单:
require('express-async-errors'); // just require!
app.use(async (req, res) => {
const user = await User.findByToken(req.get('authorization')); // could possibly throw error, implicitly does catch and next(err) for you
// throw some error and let it be implicitly handled !!
if (!user) throw Error("access denied");
});
app.use((err, req, res, next) => {
// handle error
console.error(err);
});
看看这个express async errors
(可能有人和你有相同的想法)它就像一个charm@naga elixir jar一样工作。请您将此评论转换为答案,我将接受它处理程序(req,res,next)。如果处理程序不是异步函数(如果我们在应用程序中的每个路由处理程序上应用handlepromiserexing
),则catch(next)
版本的handlepromiserexing
将不起作用是的,但OP询问了如何使用通用方法处理承诺拒绝。您的解决方案的问题是,当我请求API端点时,我的浏览器将永远挂起,并且由于未处理的承诺拒绝而失败。实际上,它对我有效,无需手动抛出错误。我做了一些测试,检查应用程序在承诺被拒绝时回复了500次,并且通过了测试,而不需要在处理程序中抛出错误。Express有现成的错误处理程序,如果(!user)抛出错误(“访问被拒绝”),则会在出现错误时以500作为响应
如果您引用这一行,author意味着您可以在路由中抛出错误,而不是执行next(error)
,包会隐式地为您执行此操作。这只是一个可以抛出错误的示例。
require('express-async-errors'); // just require!
app.use(async (req, res) => {
const user = await User.findByToken(req.get('authorization')); // could possibly throw error, implicitly does catch and next(err) for you
// throw some error and let it be implicitly handled !!
if (!user) throw Error("access denied");
});
app.use((err, req, res, next) => {
// handle error
console.error(err);
});