Спасибо всем, кто опубликовал большие / большие идеи.Однако оказалось, что Promise.each
хорошо работает с knex
, и я допустил ошибку, вызвав commit
внутри then
какого-то отдельного promises
во время цикла, что вызвало Error: Transaction query already complete
при следующей попытке транзакциипоследующий цикл. Причина: Не было необходимости вызывать commit
с контекстом / блоком транзакции knex, так как он автоматически запускается в этом контексте.
Чтобы отметить ответ ниже:
Использование Knex
с Promise.each
требует от вас прослушивания возможного отклонения внутри блока then
каждого обещания и с try/catch
, а в некоторых случаях явного отклонения , в противном случае последующиеОбещания / значения будут продолжать цикл, и это не может сделать базу данных атомарной !!!
knex.transaction(function(trx) {
return Promise.map(array, function(item) {
return trx.insert(item).into('table')
.then(returnedFields => {
try{
//do some validation/operation and return the result or the returnedFields themselves as input in the next loop.
/* START Testing a case of rejection */
if (array.indexOf(item) === 3) {
//uncomment the code below to test
//throw new Error('BreakException');
}
/* END */
}catch(err){
fail=true;
}
}).then(val => {
if (fail) {
trx.rollback()//you can ignore this as is automatically triggered here - tested
return Promise.reject(new Error('Rejected'))
}
return val
})
.catch(err => {
fail = true
trx.rollback()//you can ignore this as is automatically triggered here - tested
return Promise.reject(new Error('Rejected'))
});
});
})
.then(function(inserts) {
console.log(inserts.length + 'Items saved.');
})
.catch(function(error) {
console.error(error);
})