/ / Utilizzo di cicli e promesse nelle transazioni in Sequelize: javascript, node.js, express, promise, sequelize.js

Utilizzo di cicli e promesse nelle transazioni in Sequelize: javascript, node.js, express, promise, sequelize.js

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

Sto cercando di capire come usare 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 è sbagliato 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);
});

risposte:

23 per risposta № 1

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

Non credo che sia necessario catch all'interno di sequelize transazioni come penso che salta fuori al trucco sulla transazione

Ci scusiamo per la formattazione. Sul cellulare.

Promise.all attenderà che tutte le promesse ritornino (o falliscano) prima di eseguire il .then e il .then la callback sarà tutta la promessa di ogni matrice


5 per risposta № 2

È necessario utilizzare i costrutti di loop incorporati di bluebird che vengono forniti con il 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

1 per risposta № 3

A seconda dell'implementazione di Node.js, questo può essere d'aiuto. Ho lo stesso setup usando express, POSTGRES e sequelize.

Personalmente preferisco l'implementazione async / await (ES6) a quel punto / catch in quanto è più facile da leggere, inoltre la creazione di una funzione che può essere chiamata esternamente migliora la riutilizzabilità.

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

0 per risposta № 4

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