如何将第三方异步回调函数runTransaction改造为异步生成器模式?
如何将第三方事务函数转换为异步生成器模式?
可行实现方案
通过Promise桥接回调与异步生成器的执行流程,严格保证BEGIN→UPDATE→COMMIT的顺序:
async *transactionGenerator() { const clientPromise = new Promise(resolve => { runTransaction(async client => { // 将client和恢复执行的函数传递给生成器 await new Promise(resume => resolve({ client, resume })); }); }); const { client, resume } = await clientPromise; try { // 交出client控制权,暂停生成器 yield client; } finally { // 恢复runTransaction回调的执行,触发COMMIT resume(); } } async function main() { const gen = transactionGenerator(); const { value: client } = await gen.next(); try { // 执行事务内的数据库操作 await client.query("UPDATE ..."); } finally { // 必须调用next()触发生成器的finally块,完成事务提交 await gen.next(); } }
方案原理
- 用嵌套Promise实现回调内的暂停:当
runTransaction执行到回调时,不直接完成回调,而是通过Promise将数据库客户端和恢复执行的resume函数传递给生成器。 - 生成器
yield出客户端后暂停,直到调用gen.next()才进入finally块,调用resume()让runTransaction的回调继续执行,最终触发finally里的COMMIT。 - 全程严格遵循事务执行顺序,避免提交与业务操作并行。
原方案失败原因分析
- 方案一:
yield关键字只能直接存在于生成器函数体内,无法在嵌套的async回调中使用(该回调并非生成器函数),因此触发语法错误。 - 方案二:直接在Promise中
resolve(client)会导致runTransaction的回调立即执行完毕,COMMIT会与你的UPDATE操作并行执行,破坏了事务的顺序性。
内容的提问来源于stack exchange,提问作者user3908406
相关产品推荐
相关产品推荐

