我有以下来自第三方软件包的功能,我无法修改
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);
})
})
}
知道如何实现这一目标吗?
你可以写
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 ...");
}