将异步回调转换为异步生成器模式

问题描述 投票:0回答:1

我有以下来自第三方软件包的功能,我无法修改

async function runTransaction(callback) {
   const client = await createClient();
   try {
       await client.query("BEGIN");
       await callback(client);
   } finally {
       await client.query("COMMIT");
   }
}

通常我必须创建一个异步函数并将其传递给

runTransaction

async function update(client) {
   await client.query("UPDATE ...")
}


await runTransaction(update);

我想知道是否有办法在异步生成器模式中使用

runTransaction
。这是我的草图。我想要的最终结果是
BEGIN
然后
UPDATE
然后
COMMIT


async *clientGenerator() {
   await runTransaction(async client => {
      yield client
   });
   // this will not work as yield can't be used in a callback
}


async function main() {
   const dbClientGenerator = await clientGenerator();
   const dbClientHolder = await dbClientGenerator.next();
   await dbClientHolder.value.query("UPDATE ...");
}

我也在下面尝试过,但是回调与

await client.query("COMMIT");
中的
runTransaction
同时被调用。

async *clientGenerator() {
   yield new Promise(resolve => {
      runTransaction(async client => {
          resolve(sql);
      })
    })
}

知道如何实现这一目标吗?

javascript node.js async-await dispose
1个回答
0
投票

你可以写

async function* transaction() {
    const client = await createClient();
    try {
        await client.query("BEGIN");
        yield client;
    } finally {
        await client.query("COMMIT");
    }
}

并将其用作

for await (const client of transaction()) {
    await client.query("UPDATE ...");
}

但这并不比

更好(而且可能更令人困惑)
await runTransaction(async (client) => {
    await client.query("UPDATE ...");
});

这确实没有什么问题。它被称为“承诺处理程序模式”,并保证在完成后正确清理资源。它可能会被显式资源管理提案中的一次性文件取代,这将允许写入 { await using client = transaction(); await client.query("UPDATE ..."); }

© www.soinside.com 2019 - 2024. All rights reserved.