Reputation: 985
I am trying to write a Sequelize
migration script win which I am trying to update my database but it is having many asynchronous operations (database queries and then updating database with particular id)
Here is my code
return db.organizationEntries
.findAll()
.then((entries) => {
return entries.forEach(entry => {
console.log(entry);
db.organizationEntries
.findAll({
attributes: [
[
db.sequelize.fn(
'MAX',
db.sequelize.col('organizationEntries.serial_number')
),
'maximum_serial_no'
]
],
where: {
organizationId: entry.organizationId
}
})
.then(orgEntry => {
console.log(orgEntry[0].dataValues.maximum_serial_no);
let data = { serialNumber: orgEntry[0].dataValues.maximum_serial_no + 1 };
console.log(data)
//problem
db.organizationEntries.update(data, {
where: {
id: entry.id
}
})
.then((result) => {
console.log(result);
})
});
// promises.push(promise);
});
// return Promise.all(promises);
})
Actually what I am trying to do is I am trying to take the list of all orgEntries
from the database and then I am finding maximum serial number for that organization_id
and then updating that particular orgEntry and like this all these operations in a loop
Now the problem is coming all the things are going in order but after finding max_serial_no
it is not updating the database and I am not able to resolve what I should do to make that asynchronous call work in this order
Upvotes: 0
Views: 100
Reputation: 93
I think you can solve this in two ways:
Simultaneously Promises
In a following code I removed forEach in favor of Promise.all()
and map()
map()
method create (and return) a new array with the results of calling a provided function on every element in the calling array.Example:
let numbers = [1, 2, 3]
let doubledNumbers = numbers.map(n => n * 2)
// doubledNumbers [2, 4, 6]
Promise.all()
method take an array of Promises as argument and returns a single Promise that will be resolved when all promises will be resolved or rejected if one promise failedExample:
let promise1 = findUserById(5)
let promise2 = findUserFriends(5)
Promise.all([promise1, promise2])
.then(values => {
// values: [user object, list of user friends]
})
Result:
db.organizationEntries.findAll()
.then(entries => {
return Promise.all(entries.map(entry => {
console.log(entry)
return db.organizationEntries.findAll({
where: {
organizationId: entry.organizationId
},
attributes: [
[
db.sequelize.fn('MAX', db.sequelize.col('organizationEntries.serial_number')),
'maximum_serial_no'
]
]
})
.then(orgEntry => {
console.log(orgEntry[0].dataValues.maximum_serial_no)
let data = { serialNumber: orgEntry[0].dataValues.maximum_serial_no + 1 }
console.log(data)
return db.organizationEntries.update(data, { where: { id: entry.id } })
})
}))
})
.then(result => {
// result: Array of updated organizationEntries
console.log(result)
})
Step by step Promises with reduce()
method
reduce()
method applies a function against an accumulator and each element in the array (from left to right) to reduce it to a single value. (from MDN web docs)Example:
let items = [{ name: 'pencil', price: 2 }, { name: 'book', price: 10 }]
let total = items.reduce((total, item) => total += item.price, 0)
// total: 12
Result:
db.organizationEntries.findAll()
.then(entries => {
return entries.reduce((previousPromise, entry) => {
console.log(entry)
return previousPromise
.then(_ => {
return db.organizationEntries.findAll({
where: {
organizationId: entry.organizationId
},
attributes: [
[
db.sequelize.fn('MAX', db.sequelize.col('organizationEntries.serial_number')),
'maximum_serial_no'
]
]
})
})
.then(orgEntry => {
console.log(orgEntry[0].dataValues.maximum_serial_no)
let data = { serialNumber: orgEntry[0].dataValues.maximum_serial_no + 1 }
console.log(data)
return db.organizationEntries.update(data, { where: { id: entry.id } })
})
.then(updatedEntry => {
console.log(updatedEntry)
})
}, Promise.resolve())
})
.then(result => {
// result: Last updated organization entry
console.log('finished')
})
Upvotes: 2