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

时间:2016-05-05 13:18:04

标签: node.js postgresql transactions pg-promise

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

控制我正在使用 pg-transaction 的语句链。

我的问题是我必须始终运行2个第一个INSERTS,但我有条件运行第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 run it always 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 ,但无法找到解决此问题的方法。

欢迎任何建议!

谢谢!

1 个答案:

答案 0 :(得分:2)

手动交易管理是一条危险的道路,试图避开它! ;)

以下是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
        });
}

或者,如果您更喜欢ES6发电机:

function (req, res) {
    db.tx(function * (t) { // automatic BEGIN
            let data = yield t.one('INSERT_1 VALUES(...) RETURNING id', paramValues);
            let q = yield t.none('INSERT_2 VALUES(...)', data.id);
            if (req.body.value != null) {
                return yield 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
        });
}