Using loops and promises in transactions in Sequelize

You'll need to use the built in looping constructs of bluebird which ships with sequelize:

    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

You should use a 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);
    });

I don't believe you need to catch within sequelize transactions as I think it jumps out to the catch on the transaction

Sorry for formatting. On mobile.

Promise.all will wait for all promises to return (or fail) before running the .then, and the .then callback will be all the promise data from each array


Depending on your implementation of Node.js this may help. I have the same setup using express, POSTGRES and sequelize.

Personally I'd prefer the async/await (ES6) implementation over then/catch as it is easier to read. Also creating a function that can be called externally improves re-usability.

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;
    }
  }
}