使用 NodeJS 和 Postgres 的事务链中的可选 INSERT 语句 [英] Optional INSERT statement in transaction chain using NodeJS and Postgres

查看:24
本文介绍了使用 NodeJS 和 Postgres 的事务链中的可选 INSERT 语句的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 NodeJS/Postgres 构建一个简单的 web 应用程序,它需要在数据库中进行 3 次插入.

I'm building a simple webapp using NodeJS/Postgres that needs to make 3 insertions in the database.

为了控制语句链,我使用了 pg-transaction.

To control the chain of statements I'm using pg-transaction.

我的问题是我必须始终运行第 2 个 INSERTS,但我有条件运行第 3 个.

My problem is that I have to always run the 2 first INSERTS, but I have a condition to run the 3rd one.

也许我的代码可以以更好的方式构建(欢迎提出建议).

Maybe my code could be built in a better manner (suggestions are welcome).

这是一个伪代码:

function(req, res) {
  var tx = new Transaction(client);
  tx.on('error', die);
  tx.begin();
  
  tx.query('INSERT_1 VALUES(...) RETURNING id', paramValues, function(err, result) {
    if (err) {
      tx.rollback();
      res.send("Something was wrong!");
      return;
    }
    
    var paramValues2 = result.rows[0].id;
    tx.query('INSERT_2 VALUES(...)', paramValues2, function(err2, result2) {
      if (err) {
        tx.rollback();
        res.send("Something was wrong!");
        return;
      }
      
      // HERE'S THE PROBLEM (I don't want to always run this last statement)
      // If I don't run it, I will miss tx.commit()
      if (req.body.value != null) {
        tx.query('INSERT_3 VALUES(...)', paramValues3, function(err3, result3) {
          if (err) {
            tx.rollback();
            res.send("Something was wrong!");
            return;
          }
        
          tx.commit();
          res.send("Everything fine!");
        });
      }
    });
  });
}

在每次查询后重复三遍相同的if (err) {}看起来很丑陋.

It looks so ugly to repeat three times the same if (err) {} after each query.

尝试检查一些选项,我找到了 Sequelize,但找不到解决此问题的方法.

Trying to check some options I found Sequelize, but couldn't see a way to solve this problem with it.

欢迎提出任何建议!

谢谢!

推荐答案

手动事务管理是一条危险的道路,尽量远离它!;)

Manual transaction management is a treacherous path, try to steer away from that! ;)

以下是在 pg-promise 的帮助下正确执行此操作的方法:

Here's how to do it properly, with the help of pg-promise:

function(req, res) {
    db.tx(t => { // automatic BEGIN
            return t.one('INSERT_1 VALUES(...) RETURNING id', paramValues)
                .then(data => {
                    var q = t.none('INSERT_2 VALUES(...)', data.id);
                    if (req.body.value != null) {
                        return q.then(()=> t.none('INSERT_3 VALUES(...)', data.id));
                    }
                    return q;
                });
        })
        .then(data => {
            res.send("Everything's fine!"); // automatic COMMIT was executed
        })
        .catch(error => {
            res.send("Something is wrong!"); // automatic ROLLBACK was executed
        });
}

或者,如果您更喜欢 ES7 语法:

Or, if you prefer ES7 syntax:

function (req, res) {
    db.tx(async t => { // automatic BEGIN
            let data = await t.one('INSERT_1 VALUES(...) RETURNING id', paramValues);
            let q = await t.none('INSERT_2 VALUES(...)', data.id);
            if (req.body.value != null) {
                return await t.none('INSERT_3 VALUES(...)', data.id);
            }
            return q;
        })
        .then(data => {
            res.send("Everything's fine!"); // automatic COMMIT was executed
        })
        .catch(error => {
            res.send("Something is wrong!"); // automatic ROLLBACK was executed
        });
}

更新

在示例中用 ES7 async/await 替换了 ES6 生成器,因为 pg-promise 从 9.0.0 版本开始不再支持 ES6 生成器

Replaced ES6 generators with ES7 async/await in the example, because pg-promise stopped supporting ES6 generators from version 9.0.0

这篇关于使用 NodeJS 和 Postgres 的事务链中的可选 INSERT 语句的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆