捕获 async-await 快速路由处理程序中的所有错误
Posted
技术标签:
【中文标题】捕获 async-await 快速路由处理程序中的所有错误【英文标题】:Catching all errors in async-await express route handlers 【发布时间】:2018-10-07 09:47:54 【问题描述】:假设我有这样的路线:
app.get('/broken', (req, res) =>
throw new Error('Broken!');
);
这永远不会向客户端发送响应。
但是,我可以为所有错误添加一个中间件:
const errorMiddleware = (error, req, res, next) =>
if (error)
console.error(error);
return res.status(500)
.json(
message: 'Internal server error',
);
next(error);
;
但这不适用于async
路由,因为它们不直接throw
。
例如,这将不起作用:
app.get('/broken', async (req, res) =>
throw new Error('Broken!');
);
所以我可以像这样创建一个包装器:
const asyncRoute = f => (req, res, next) =>
return Promise.resolve(f(req, res, next)).catch(next);
;
app.get('/broken', asyncRoute(async (req, res) =>
throw new Error('Broken!');
));
但这真的很痛苦,因为现在我必须为每条路线调用这个函数!
有什么更好的方法来处理这个问题?
Is there a way to wrap an await/async try/catch block to every function?的答案就是我上面描述的 how to use Promise with express in node.js? 的答案不使用
await
【问题讨论】:
你认为路由回调async
有什么好处? Express 不使用承诺,所以......纯粹是为了在其中获得await
语义吗?如果是这样,您的包装器就是这样做的正确方法。
(你可以看看Koa。)
好吧,我的一些路由需要多次 async
调用(例如数据库、API、bcrypt),因此在 async
上下文中更容易编写。
@T.J.Crowder 如果我没有通过承诺(例如123
),那么我希望强制承诺(例如Promise.resolve(123)
)。请注意,Promise.resolve(Promise.resolve(x))
被展平为Promise.resolve(x)
。
好的。我没有看到任何理由将非承诺传递给名为asyncRoute
的东西,所以我没有意识到你想要处理这个问题。 :-)
【参考方案1】:
基本上,您不想直接将async
函数传递给 Express 的app.get
,因为app.get
不处理函数返回的承诺。所以你需要包装那些async
处理程序(就像你正在做的那样)。
您可以通过在模块顶部给自己一个实用方法来避免每次都这样做:
const appGet = handler => app.get(asyncRoute(handler));
然后用它代替app.get
:
appGet('/broken', async (req, res) =>
throw new Error('Broken!');
);
在某个时候(可能不是现在),您可能想查看Koa。
【讨论】:
以上是关于捕获 async-await 快速路由处理程序中的所有错误的主要内容,如果未能解决你的问题,请参考以下文章