Использование циклов и promises в транзакциях в Sequelize
В настоящее время я создаю приложение Nodejs, Express, Sequelize (w. PostgreSQL) и столкнулся с несколькими проблемами при использовании promises вместе с транзакциями и циклами.
Я пытаюсь выяснить, как использовать циклы for в транзакции. Я пытаюсь пропустить список членов и создать нового пользователя в базе данных для каждого из них.
Я знаю, что следующий код неверен, но он показывает, что я пытаюсь сделать.
Может ли кто-нибудь указать мне в правильном направлении?
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);
});
Ответы
Ответ 1
Вы должны использовать 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);
});
Я не верю, что вам нужно catch
в продолжении транзакций, поскольку я думаю, что он перескакивает на уловку транзакции
Извините за форматирование. На мобильном телефоне.
Promise.all будет ждать, пока все promises вернутся (или не сработают) перед запуском .then, а обратный вызов .then
будет представлять собой все данные обещания из каждого массива
Ответ 2
Вам нужно использовать встроенные петлевые конструкции bluebird, которые поставляются с 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
Ответ 3
Сначала: https://caolan.github.io/async/docs.html
Итак, легко:
// 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);
}
});
});
}