如何在passport-local-mongoose中结合Mongoose事务使用?
可以将passport-local-mongoose与Mongoose事务结合使用,你的代码问题出在这几点:
User.register是回调风格的方法,直接用await不会等待它执行完成,会导致事务提前提交或第二个文档创建时第一个操作还未完成。- 你把
session参数放在了回调的位置,register的第四个参数是回调函数,并非配置选项,所以session根本没被传入内部的保存逻辑。
正确的实现方式
第一步:把register转为Promise风格
用Node.js的util.promisify包装该方法,或者手动封装成Promise,这样就能用await等待执行结果。
第二步:确保所有数据库操作绑定到事务session
不管是register内部的用户保存,还是第二个文档的创建,都要明确指定session选项。
完整代码示例
const util = require('util'); // 把register转成Promise版本,必须绑定User上下文 const registerUser = util.promisify(User.register).bind(User); const session = await db.startSession(); session.startTransaction(); try { // 执行注册,正确传递session选项 const user = await registerUser( new User({ /* 用户名等账号信息 */ }), req.body.password, { session: session } ); // 创建第二个用户数据文档,同样指定session await UserProfile.create( { userId: user._id, /* 其他用户数据 */ }, { session: session } ); await session.commitTransaction(); } catch (err) { await session.abortTransaction(); throw err; // 抛出错误让上层处理 } finally { // 无论成功失败,都要关闭session避免泄漏 session.endSession(); }
关键细节说明
- 用
util.promisify包装User.register时,必须用.bind(User)绑定上下文,否则内部this指向会出错。 - 所有数据库写入操作(包括
register内部的user.save())都必须绑定同一个事务session,否则事务不会生效。 - 用
finally块关闭session,避免因错误导致session资源泄漏。
内容的提问来源于stack exchange,提问作者KorbenDose
相关产品推荐
相关产品推荐

