一尘不染

使用NodeJS和Postgres的事务链中的可选INSERT语句

node.js

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

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

我的问题是我必须总是先运行第2个插件,但是我有条件要运行第3个插件。

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

这是一个伪代码:

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){} 看起来很丑。

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

欢迎任何建议!

谢谢!


阅读 597

收藏
2020-07-07

共1个答案

一尘不染

手动交易管理是一条危险的道路,请设法避免这种情况!;)

这是在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语法:

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/ 替换了ES6生成器await,因为pg-promise停止了从9.0.0版本开始支持ES6生成器

2020-07-07