/ / Korzystanie z pętli i obietnic w transakcjach w Sequelize - javascript, node.js, express, promise, sequelize.js

Korzystanie z pętli i obietnic w transakcjach w Sequelize - javascript, node.js, express, promise, sequelize.js

Obecnie buduję aplikację Nodejs, Express, Sequelize (w. PostgreSQL) i mam kilka problemów z wykorzystaniem obietnic wraz z transakcjami i pętlami.

Próbuję dowiedzieć się, jak używać pętli dla transakcji. Próbuję przeglądać listę członków i utworzyć nowego użytkownika w bazie danych dla każdego z nich.

Wiem, że poniższy kod jest nieprawidłowy, ale pokazuje, co próbuję zrobić.

Czy ktoś może wskazać mi właściwy kierunek?

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

Odpowiedzi:

23 dla odpowiedzi № 1

Powinieneś użyć 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);
});

Nie wierzę, że musisz catch w ramach kolejnych transakcji, ponieważ myślę, że przeskakuje do połowy transakcji

Przepraszamy za formatowanie. Na komórce.

Obietnica.all będzie czekać na wszystkie obietnice, aby powrócić (lub nie) przed uruchomieniem. Then, a .then callback to wszystkie obiecujące dane z każdej tablicy


5 dla odpowiedzi nr 2

Musisz użyć wbudowanych pętli konstruktorów bluebirda, które są dostarczane z 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 dla odpowiedzi nr 3

W zależności od implementacji Node.js może to pomóc. Mam tę samą konfigurację używając express, POSTGRES i sequelize.

Osobiście preferuję implementację async / await (ES6) nad / catch, ponieważ jest to łatwiejsze do odczytania, a tworzenie funkcji, którą można nazwać zewnętrznie, poprawia ponowne użycie.

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 dla odpowiedzi nr 4

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

Tak łatwo:

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