2016-02-29 10 views
12

Attualmente sto creando un'app Nodejs, Express, Sequelize (w. PostgreSQL) e ho incontrato alcuni problemi nell'usare promesse insieme a transazioni e loop.Utilizzo di loop e promesse nelle transazioni in Sequenza

Sto cercando di capire come utilizzare un ciclo for in una transazione. Sto cercando di scorrere un elenco di membri e creare un nuovo utente nel database per ciascuno di essi.

So che il seguente codice è errato ma mostra ciò che sto cercando di fare.

Qualcuno può indicarmi la giusta direzione?

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

risposta

19

È necessario utilizzare un 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); 
    }); 

non credo è necessario catch all'interno di transazioni sequelize come penso che salta fuori per il fermo sulla transazione

Siamo spiacenti per la formattazione . Sul cellulare.

Promise.all attenderà tutte le promette di tornare (o non riescono) prima di eseguire l'.then, e il callback .then sarà tutti i dati promessa da parte ogni array

+0

Grazie per la risposta, ma ricevo un errore che mi dice che ho bisogno di restituire una catena di promesse alla transazione. Ho provato ad aggiungere "return" prima di ogni Promise.all, ma poi ho ricevuto _ "Il commit di rifiuto non gestito è stato chiamato su questa transazione (fc7be023-1980-455e-9934-7816420daa2b), non puoi più usarlo" _ – ReturnToZero

+1

Sì, manca un ritorno e nulla viene mai spinto all'utentePromises. –

+0

@BenjaminGruenbaum, grazie, l'ho fatto ieri sul cellulare e non ho mai avuto la possibilità di tornare indietro e di aggiornarlo. Aggiornerò dopo quando posso – Datsik

4

È necessario utilizzare il costruito nel loop costrutti di Bluebird fornito con 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(err); // convert to node err-back syntax for express 
+0

Anche codice funzionante e molto elegante. Non è stato possibile ottenere il '.nodeify (err); Dice err non definito. Non ho usato il nodo prima, quindi probabilmente mi manca qualcosa. – ReturnToZero

+0

Dovrebbe essere il nodo (successivo) - spiacente –

0

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

Così, facilmente:

// 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

Benvenuti in Stack Overflow, grazie per l'offerta di una risposta. Per favore controlla: https://stackoverflow.com/help/how-to-answer – Daniel