Reputation: 13
I live in the PHP world but I am attempting to build out a REST Api using Node.
I have been stuck all day of trying to return an array of results from a for loop. Basically I am passing an array of field_name:field_value. I want to push the result from the update into an array to return. I can get it to log in the console but no further.
Here is a sample post json data
{
"first_name":"Jeff",
"phone":"4855555555"
}
Here is the function and loop
function UpdateKey(user_id, key, value, cb) {
connection.query('UPDATE users SET ' + key + ' = ? WHERE id = ? LIMIT 1', [value, user_id], function(err, results) {
if (err) {
callback = key + " update failed.";
} else {
callback = key + " was updated.";
}
cb(callback);
});
}
for (myKey in post_data) {
UpdateKey(user_id, myKey, post_data[myKey], function(id) {
console.log(id);
});
}
res.send(JSON.stringify({ "status": 200, "error": "", "response": my_results_here }));
I have been researching async but not sure the best route here. Any help would be great!
Upvotes: 1
Views: 35
Reputation: 19372
The solution You want:
const updateUserField = (userId, field, value) => {
return Promise((resolve) => {
const query = 'UPDATE users SET ' + field + ' = ? WHERE id = ?';
const data = [value, userId];
connection.query(query, data, (error) => {
if (error) return resolve(field + ' update failed');
resolve(field + ' was updated');
});
});
};
router.post('/user/:id', async (req, res) => {
const userId = req.params.id;
const data = req.body;
const response = [];
for (const field in data) {
response.push(
await updateUserField(userId, field, data[field])
);
}
res.status(200).send({
response
});
});
or in parallel:
router.post('/user/:id', async (req, res) => {
const userId = req.params.id;
const data = req.body;
const response = await Promise.all(
Object
.keys(data)
.map(field => updateUserField(userId, field, data[field]))
);
res.status(200).send({
response
});
});
Correct solution
As I understand You want to get post data and update record in users table.
So why not just do it in one query?
Try this way:
const updateUser = (userId, data) => {
return Promise((resolve, reject) => {
const query = 'UPDATE users SET ? WHERE id = ?';
connection.query(query, [data, userId], (error) => {
if (error) return reject(error);
resolve();
});
});
};
router.post('/user/:id', async (req, res) => {
try {
const userId = req.params.id;
const data = req.body;
await updateUser(userId, data);
res.status(200).send({
message: 'User account successfully updated'
})
}
catch (error) {
console.error(error);
res.status(500).send({
message: 'Failed update user account'
});
}
});
But better think about using ORM i.e. Sequelize for security, validation and etc features that eases dev's life.
Upvotes: 1
Reputation: 138557
You could collect all results in an array and send that when the arrays size equals the keys size:
const keys = Object.keys(post_data);
const response = [];
for(const myKey of keys) {
UpdateKey(user_id, myKey, post_data[myKey], function(id) {
response.push(id);
if(keys.length === response.length) {
res.send(JSON.stringify({
status: 200,
error: "",
response
}));
}
});
}
Upvotes: 1