Suvigy Mishra
Suvigy Mishra

Reputation: 3

Async/Await not working with mongoose findOne

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

Answers (2)

Denis Malykhin
Denis Malykhin

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

Ali Nauman
Ali Nauman

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

Related Questions