来自 pg-promise 常见问题解答 Why use method batch instead of promise.all? :
It is quintessential to settle all the promises-queries created within your task or transaction, before the connection is released
我不明白为什么这会成为一个问题。
例如,当我们有一组像这样的查询时:
[
t.any("SELECT pg_sleep(2) as a"),
t.any('this will fail'),
t.any("SELECT pg_sleep(3) as b")
]
注意:pg_sleep
仅用于测试。
在生产中,这将是 Insert/Update/Delete
语句。我们只想在全部成功时提交事务:即当其中任何一个失败时返回错误。
当我们使用batch()时:
- 第一个 promise 将在 2 秒后解决
- 第二个 promise 将被拒绝
- 第三个查询仍将发送到数据库并在 3 秒后返回
- 最后(总共 5 秒后),
batch
完成,我们可以向调用者返回错误。
当我们使用Promise.all()时:
- 第一个 promise 将在 2 秒后解决
- 第二个 Promise 将拒绝 - 这将回滚事务并释放数据库连接
- 现在我们已经可以向调用者返回错误
- 第三个请求将立即失败,并显示
查询已释放或丢失的连接。
。无论如何,这是预料之中的,所以我们可以忽略它。
所以我想说 Promise.all
更好,因为:
- 它在第一个错误发生后立即返回
- 甚至不会向数据库发送第三个无用的查询
我错过了什么?
这是否可能会导致其他问题:例如断开的连接返回到池等。
最佳答案
方法batch适合可能创建动态数量的查询的场景。
它确保所有查询都得到解决(解决或拒绝),因此您最终不会针对关闭的连接执行查询,并收到针对已释放或丢失的连接进行查询
错误。开始让这些错误发生在上下文之外可能会很糟糕/令人困惑,并且您无法诊断发生了什么。
方法 Promise.all
不会解决 Promise,当数组中的第一个 Promise 拒绝时,它会停止处理并拒绝。
还有 while 方法 batch仍然非常有用,因为它在处理值的方式上更加灵活,并且比 Promise.all 提供更好的结果/错误详细信息,现在不再需要使用它。它是在 ES5 时代开发的,当时 async/await
还不存在。但今天您可以轻松地将其替换为 async/await
:
旧样式:
db.task('get-all-records', t => {
return t.batch([
t.any('SELECT * FROM apples'),
t.any('SELECT * FROM oranges')
]);
})
.then([apples, oranges] => {
// process data here
})
.catch(error => {});
新风格:
const {apples, oranges} = await db.task('get-all-records', async t => {
const apples = await t.any('SELECT * FROM apples');
const oranges = await t.any('SELECT * FROM oranges');
return {apples, oranges};
});
上面两个例子的结果是相同的,尽管它们在执行逻辑方面并不相同,因为第一个例子是完全异步的,而后者使用了async/await
,这些是阻塞操作,如果之前的查询失败,它们甚至会阻止您创建下一个查询。
额外内容
执行多个独立查询(彼此不依赖)时,性能最佳的方法是将所有查询连接起来,并将它们作为一个查询执行。
为此,有方法 helpers.concat ,加上数据库方法multi ,处理多个结果:
const queries = [
{query: 'SELECT * FROM apples WHERE color = $1', values: ['green']},
'SELECT * FROM oranges'
];
const sql = pgp.helpers.concat(queries);
const [apples, oranges] = await db.multi(sql);
您甚至不需要事务,除非您的某些独立查询更改了数据。
关于pg-promise - 为什么我们应该使用batch()而不是Promise.all?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59265583/