Giorgio Todeschini
asked on
How to modify an object inside a Promise
I'm developing a REST API server using Nodejs and Hapi (https://hapi.dev/) framework and Sequelize (https://sequelize.org/) to access to a MYSQL database.
I have the following route function handler:
Unfortunately, in the result of the function, I get the task array empty (like the following).
This (I think) because the nested findAll(...) function is asynchronous, but I can't find a way to wait that the elaboration is finished before to execute the line "return h.response(tasks);"
Could you please help me?
I have the following route function handler:
async function workload(request, h) {
// First I perform a query and I get a resultset
const result = await this.userModel.findAll(options);
// Then I would like to replace the "task" property of each record with a result of another query
const tasks = result.map(row => {
const user = row.get();
user.tasks = []; // Initialize with an empty array
const user_tasks = this.taskModel.findAll({
attributes: [ "week", [ Sequelize.fn("SUM", Sequelize.col('`Task`.`ore_prev`')), "estimatedHours" ] ],
where: {
week: { [Op.and]: [ { [Op.gte]: startWeek }, { [Op.lte]: endWeek } ]}
},
include: {
model: this.projectSubphaseUserModel,
attributes: [],
where: {
user: user.id
}
},
group: [ 'week' ],
raw: true
})
.then(function (value) {
user.tasks.push(value); // Fill the array with the result of the subquery
return user;
})
.finally(() => {
console.log(user.tasks); // Here I found the array properly filled
});
return user;
});
return h.response(tasks);
}
Unfortunately, in the result of the function, I get the task array empty (like the following).
[
{
"id": 276,
"role": 4,
"initials": "JD",
"name": "John Doe",
"tasks": []
}
]
Now, I understood that the problem is that when the array has filled by the nested findAll function, the main function has already returned his result with the array still empty.This (I think) because the nested findAll(...) function is asynchronous, but I can't find a way to wait that the elaboration is finished before to execute the line "return h.response(tasks);"
Could you please help me?
check this : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all
ASKER
Dear @leakim971,
thanks for your help. I tried to follow the page you sent me, and I changed my code as follows:
Unfortunately, the code of the expression inside the result.map() function returns the user object before that the code inside the function this.taskModel.findAll() changes the value of the task property.
I would like to do this:
Another try thing that I tried to do is:
Could you please help me?
Thanks in advance
thanks for your help. I tried to follow the page you sent me, and I changed my code as follows:
const result = await this.userModel.findAll(options);
const tasks = result.map(row => {
const user = row.get();
user.tasks = []; // Initialize with an empty array
const user_tasks = this.taskModel.findAll({
attributes: [ "week", [ Sequelize.fn("SUM", Sequelize.col('`Task`.`ore_prev`')), "estimatedHours" ] ],
where: {
week: { [Op.and]: [ { [Op.gte]: startWeek }, { [Op.lte]: endWeek } ]}
},
include: {
model: this.projectSubphaseUserModel,
attributes: [],
where: {
user: user.id
}
},
group: [ 'week' ],
raw: true
});
Promise.all([ user_tasks ]).then((values) => {
user.tasks.push(values);
});
// I would like to pause my code here until the user.tasks have changed by the expression here before
return user; // Here returns the user before that the user_tasks Promise has executed
});
Unfortunately, the code of the expression inside the result.map() function returns the user object before that the code inside the function this.taskModel.findAll() changes the value of the task property.
I would like to do this:
- Find all my users
const result = await this.userModel.findAll(options);
- Loop through the users returned by (1) and find the user's tasks
const user_tasks = this.taskModel.findAll({ attributes: [ "week", [ Sequelize.fn("SUM", Sequelize.col('`Task`.`ore_prev`')), "estimatedHours" ] ], where: { week: { [Op.and]: [ { [Op.gte]: startWeek }, { [Op.lte]: endWeek } ]} }, include: { model: this.projectSubphaseUserModel, attributes: [], where: { user: user.id } }, group: [ 'week' ], raw: true });
- To copy the array resulting by (3) to the array of the property user.tasks.
Another try thing that I tried to do is:
const tasks = result.map(row => {
const user = row.get();
user.tasks = []; // Initialize with an empty array
const user_tasks = await this.taskModel.findAll({
attributes: [ "week", [ Sequelize.fn("SUM", Sequelize.col('`Task`.`ore_prev`')), "estimatedHours" ] ],
where: {
week: { [Op.and]: [ { [Op.gte]: startWeek }, { [Op.lte]: endWeek } ]}
},
include: {
model: this.projectSubphaseUserModel,
attributes: [],
where: {
user: user.id
}
},
group: [ 'week' ],
raw: true
})
user.tasks = user_tasks;
return user;
});
But I get the message "SyntaxError: await is only valid in async function".Could you please help me?
Thanks in advance
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.