Reputation: 3
I'm trying to get the reply variable but when callback function is called, all I get is an empty variable. Async/await doesn't seem to be working for findOne funtion as I get the values after callback is called.
function byClanTag(tag, callback) {
clashApiClient
.clanByTag(tag)
.then((response) => {
var reply = "";
console.log("1");
response.memberList.forEach(async (member) => {
console.log("2");
await Player.findOne({ playerTAG: member.tag }, (err, player) => {
if (err) {
console.log(err);
callback("Error: ", err);
}
if (!player) {
console.log("3");
reply = reply + member.name + ": " + "Strike information doesn't exist.\n";
} else {
reply = reply + member.name + ": " + player.strikeCount + "Strikes.\n";
}
});
});
console.log("4");
callback("```" + response.name + " : \n\n" + reply + "```");
})
.catch(() => callback("Error: Something went wrong while getting data!"));
}
The expected log output is 1 (23)*n times 4 but I end up getting 1 (2)*n times 4 (3)*n times
Upvotes: 0
Views: 988
Reputation: 347
It makes sense to use Promise.all to make all requests in parallel instead of serial like so:
function byClanTag(tag, callback) {
clashApiClient
.clanByTag(tag)
.then((response) => {
const pendingPromises = response.memberList.map((member) => Player.findOne({ playerTAG: member.tag })
return Promise.all(pendingPromises)
})
.then((arrayOfResults) => {....})
.catch(() => callback("Error: Something went wrong while getting data!"));
}
However, to reduce the load on the database, the proper solution will be to get the data by an array of IDs in one request.
Upvotes: 1
Reputation: 1677
You either use callbacks or use Promises. You're trying to do both when you use await Player.findOne({ ... }, (err, player) => { ...})
.
You should update the line to be const player = await Player.findOne({ ... })
. Plus, as Rifat suggested in the comment, use the for ...of
loop for the promise to work correctly.
Upvotes: 3