wake-up-neo.com

Verwenden von Schleifen und Versprechen in Transaktionen in Sequelize

Ich baue gerade eine Nodejs, Express, Sequelize (w. PostgreSQL) -App auf und habe Probleme mit der Verwendung von Versprechen zusammen mit Transaktionen und Schleifen.

Ich versuche herauszufinden, wie man for-Schleifen in einer Transaktion verwendet. Ich versuche, eine Liste von Mitgliedern durchzugehen und für jeden von ihnen einen neuen Benutzer in der Datenbank zu erstellen. 

Ich weiß, dass der folgende Code falsch ist, aber er zeigt, was ich versuche.

Kann mir jemand die richtige Richtung zeigen?

        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);
        });
13
ReturnToZero

Sie sollten einen Promise.all verwenden

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

Ich glaube nicht, dass Sie innerhalb von sequelize-Transaktionen catch brauchen, da ich denke, dass es zum Haken bei der Transaktion springt 

Entschuldigung für die Formatierung. Auf dem Handy. 

Promise.all wartet, bis alle Versprechen zurückgegeben werden (oder fehlschlagen), bevor der .then ausgeführt wird, und der .then-Rückruf enthält alle Versprechungsdaten aus jedem Array 

27
Datsik

Sie müssen die eingebauten Schleifenkonstrukte von bluebird verwenden, die mit sequelize ausgeliefert werden:

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(err); // convert to node err-back syntax for express
5

Abhängig von Ihrer Implementierung von Node.js kann dies hilfreich sein. Ich habe das gleiche Setup mit Express, POSTGRES und Sequelize.

Persönlich würde ich die Implementierung von async/await (ES6) vorziehen/catch, da sie einfacher zu lesen ist. Das Erstellen einer Funktion, die extern aufgerufen werden kann, verbessert die Wiederverwendbarkeit.

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

Erstes: https://caolan.github.io/async/docs.html

So einfach:

// 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);
      }
    });
  });
}
0
Eri Jonhson