从pg-promise常见问题Why use method batch instead of promise.all?:
在释放连接之前,解决您在任务或事务中创建的所有promise-queries是非常典型的
我不明白为什么这应该是一个问题。
对于example,当我们有这样的查询数组时:
[
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():
时batch
,我们可以将错误返回给调用方。当我们使用Promise.all():
Querying against a released or lost connection.
。无论如何,这是预期的,因此我们可以忽略它。所以我想说Promise.all
更好,因为:
我想念什么?这是否会导致其他问题:例如断开的连接返回到池中,等等。
它确保所有查询都已解决(解决或拒绝),因此您不会最终针对封闭的连接执行查询,并得到Querying against a released or lost connection
错误。开始让那些错误发生在上下文之外可能会很糟糕/令人困惑,并且您无法诊断正在发生的事情。
方法Promise.all
不履行承诺,它停止处理并在数组中的第一个承诺拒绝时拒绝。
尽管方法batch仍然非常有用,因为它在处理值方面更加灵活,并且比Promise.all
提供更好的结果/错误详细信息,但今天不再需要使用它。它是在async/await
不存在的ES5时代开发的。但是今天您可以轻松地将其替换为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 => {});
新样式:
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}; }) .then({apples, oranges} => { // process data here }) .catch(error => {});
上面两个示例的结果将是相同的,尽管它们在执行逻辑上是不同的,因为第一个是完全异步的,而后一个使用了阻塞操作的async/await
,它们会阻止您如果创建前一个查询失败,甚至无法创建下一个查询。
我认为最好更改逻辑,以便我们不要构建一个Promise数组,而是构建一个查询字符串数组(当查询需要参数时使用format())。然后等待所有的人:
db.task(async t => {
const queries = [
"SELECT pg_sleep(2) as a",
'this will fail',
"SELECT pg_sleep(3) as b"
];
for (const q of queries) await t.any(q);
});
这种方式:
Querying against a released or lost connection
错误