'How to Await a Loop of Async Operations? [duplicate]
I have a patch endpoint that takes a body of fields to update, iterates over each field, and updates the correct value. I want to do something send a response once all those things are done, but I do not know how to await a loop of operations. If it was a singular operation I could just add .then(), but that would not work in this case. What is an elegant solution to this?
Code:
const updateUser = (req, res) => {
const db = mongoConnection.getDb();
for (key in req.body) {
db.collection('users').updateOne(
{username: req.query.username},
{$set: {[key]: req.body[key]}}
)
}
// send response once for loop is done
}
Solution 1:[1]
I think an easy answer would be hiding the for loop in an async function, then use it in the endpoint.
const updateUserField = async () =>
db.collection("users").updateOne(
{
username: req.query.username,
},
{
$set: { [key]: req.body[key] },
}
);
const updateUserEndpoint = (req, res) => {
for (let field of req.body) {
await updateUserField(field);
}
res.status(200).send('updated');
}
Then, for testing, you could wrap the endpoint with a function that injects the function itself:
const updateUserEndpoint = (userUpdateFunc) => userUpdateFunc(req, res);
This pattern is called dependency injection - when writing unit tests for the endpoint, you'd just replace userUpdateFunc with whatever mocked function you want to use. This removes the need to monkeypatch the function in the test.
Solution 2:[2]
You could mark the outer function async and await each DB update inside the loop. Then you'll know that after the loop completes, all DB updates are done.
An even better way is to run the updates in parallel since they do not depend on each other. You can use Promise.allSettled() which takes an array of promises and resolves when the last one is finished.
const updateUser = async (req, res) => {
const db = mongoConnection.getDb();
const dbUpdates = Object.entries(req.body).map((key, value) => {
return db.collection('users').updateOne(
{ username: req.query.username },
{ $set: { [key]: value }}
);
});
await Promise.allSettled(dbUpdates);
// Send response, at this point all DB updates are done
};
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Terreras |
| Solution 2 |
