如何结合express-async-handler与Mongoose Session实现事务回滚?
express-async-handler 结合 Mongoose Session 实现事务回滚
一、express-async-handler 到底干嘛用?
它就是个实用工具,帮你自动捕获异步路由/控制器里的错误,不用手动写一堆try/catch去处理Promise拒绝。只要用它包裹你的异步函数,里面抛出的任何错误都会自动传给next(),交给全局错误中间件处理,避免因为未捕获的异步错误导致服务器崩溃。
二、和 Mongoose Session 结合实现事务回滚的正确写法
你原来的代码存在几个关键问题:没开启事务、创建文档时未绑定session、未处理错误回滚。下面是修正后的完整代码:
const proc = expressAsyncHandler(async (req: Request, res: Response, next: NextFunction) => { const session = await mongoose.startSession(); try { // 第一步:启动事务 session.startTransaction(); // 核心:创建文档时必须传入session选项,才能让操作纳入事务管理 const newUser = await Data.create([{ /* 你的用户数据 */ }], { session }); const newGroup = await Group.create([{ /* 你的群组数据 */ }], { session }); // 所有操作成功后,提交事务 await session.commitTransaction(); res.status(201).json({ user: newUser, group: newGroup }); } catch (err) { // 发生错误时,立即回滚事务 await session.abortTransaction(); // 把错误传给全局错误中间件处理 next(err); } finally { // 无论成功失败,必须结束session释放资源 session.endSession(); } });
核心注意点:
- 必须绑定session到操作:所有需要纳入事务的数据库操作(比如
create、updateOne等),都要加上{ session }参数,不然这些操作不会受事务控制,回滚也无效。 - 事务的固定流程:启动事务(
startTransaction)→ 执行业务操作 → 成功提交/失败回滚。 - 释放session资源:用
finally块确保session一定会被结束,避免内存泄漏。
三、和全局错误中间件的配合
你已经定义的全局错误中间件可以直接使用,只要在catch块里调用next(err),错误就会被中间件捕获,打印堆栈并返回500响应。express-async-handler在这里的额外作用是:如果代码里有没被try/catch捕获到的错误(比如session启动失败),它会自动把错误传给next(),不会让错误变成未处理的Promise拒绝。
内容的提问来源于stack exchange,提问作者elimey
相关产品推荐
相关产品推荐

