繁体   English   中英

在 Sequelize 的事务中使用循环和承诺

[英]Using loops and promises in transactions in Sequelize

我目前正在构建一个 Nodejs、Express、Sequelize (w. PostgreSQL) 应用程序,并且在将 Promise 与事务和循环一起使用时遇到了一些问题。

我想弄清楚如何在事务中使用 for 循环。 我正在尝试遍历成员列表并在数据库中为每个成员创建一个新用户。

我知道以下代码是错误的,但它显示了我正在尝试做的事情。

任何人都可以指出我正确的方向吗?

        var members = req.body.members;
        models.sequelize.transaction(function (t) {
            for (var i = 0; i < members.length; i++) {
                return models.User.create({'firstname':members[i], 'email':members[i], 'pending':true}, {transaction: t}).then(function(user) {
                    return user.addInvitations([group], {transaction: t}).then(function(){}).catch(function(err){return next(err);});
                })
            };
        }).then(function (result) {
            console.log("YAY");
        }).catch(function (err) {
            console.log("NO!!!");
            return next(err);
        });

你应该使用Promise.all

    var members = req.body.members;
    models.sequelize.transaction(function (t) {
        var promises = []
        for (var i = 0; i < members.length; i++) {
            var newPromise = models.User.create({'firstname':members[i], 'email':members[i], 'pending':true}, {transaction: t});
           promises.push(newPromise);
        };
        return Promise.all(promises).then(function(users) {
            var userPromises = [];
            for (var i = 0; i < users.length; i++) {
                userPromises.push(users[i].addInvitations([group], {transaction: t});
            }
            return Promise.all(userPromises);
        });
    }).then(function (result) {
        console.log("YAY");
    }).catch(function (err) {
        console.log("NO!!!");
        return next(err);
    });

我认为您不需要在 sequelize 交易中catch ,因为我认为它会跳出交易中的捕获

抱歉格式化。 在移动。

Promise.all 将在运行 .then 之前等待所有 Promise 返回(或失败),并且.then回调将是每个数组中的所有.then数据

您需要使用 sequelize 附带的 bluebird 的内置循环结构:

    var members = req.body.members;
    models.sequelize.transaction(t => 
      Promise.map(members, m => // create all users
        models.User.create({firstname: m, email: m, 'pending':true}, {transaction: t})
      ).map(user => // then for each user add the invitation
         user.addInvitations([group], {transaction: t}) // add invitations
    )).nodeify(next); // convert to node err-back syntax for express

根据您对 Node.js 的实现,这可能会有所帮助。 我使用 express、POSTGRES 和 sequelize 进行了相同的设置。

我个人更喜欢 async/await (ES6) 实现而不是 then/catch,因为它更容易阅读。 还创建一个可以从外部调用的函数提高了可重用性。

async function createMemeber(req) {
let members = req.body.members;
  for (var i = 0; i < members.length; i++) {
    // Must be defined inside loop but outside the try to reset for each new member;
    let transaction = models.sequelize.transaction();
    try { 
      // Start transaction block.
      let user = await models.User.create({'firstname':members[i],  'email':members[i], 'pending':true}, {transaction});
      await user.addInvitations([group], {transaction}));

      // if successful commit the record. Else in the catch block rollback the record.
      transaction.commit();
      // End transaction block.
      return user;
    } catch (error) { 
      console.log("An unexpected error occurred creating user record: ", error);
      transaction.rollback();
      // Throw the error back to the caller and handle it there. i.e. the called express route.
      throw error;
    }
  }
}

第一: https : //caolan.github.io/async/docs.html

所以,很容易:

// requiring...
const async = require('async');

// exports...
createAllAsync: (array, transaction) => {
  return new Promise((resolve, reject) => {
    var results = [];
    async.forEachOf(array, (elem, index, callback) => {
      results.push(models.Model.create(elem, {transaction}));
      callback();
    }, err => {
      if (err) {
        reject(err);
      }
      else {
        resolve(results);
      }
    });
  });
}

如果有人正在寻找使用 async 和 await 的 typescript v4.0.5 的解决方案,那么这里对我有用。 也许你也可以在你的 javascript 应用程序上使用它,但这取决于它的版本。

const array = ['one','two','three'];
const createdTransaction = sequelize.transaction();
    
const promises = array.map(async item => {
      await model.create({
          name: item,
      },
      { transaction: createdTransaction },
     );
});

Promise.all(promises).then(async values => {
    await createdTransaction.commit();
});

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM