0

I am writing code to fetch the data from the api and save it in the mongodb database. The code I have written is:

     getSquadList: async (ctx) => {
var query = ctx.request.query;
var squadList = await getSquadsOfMatch(query.matchId);
if (squadList.length <= 1) {
  var response = await axios.get(
    `${strapi.config.currentEnvironment.getSquadListApi}?apikey=${strapi.config.currentEnvironment.cricApiKey}&unique_id=${query.matchId}`
  );

  squadList = response.data.squad;

  var match = await Match.findOne({
    unique_id: query.matchId
  });

  var team1Squad, team2Squad;

  await squadList.forEach(async squad => {
    if (squad.name === match['team-1']) {
      team1Squad = {
        name: match['team-1'],
        match_id: match['unique_id'],
        match: match['_id'],
      };

      await new Squad(team1Squad).save();
      console.log('1');
    } else if (squad.name === match['team-2']) {
      team2Squad = {
        name: match['team-2'],
        match_id: match['unique_id'],
        match: match['_id'],
      };

      await new Squad(team2Squad).save();
      console.log('2');
    }
  });

  squadList = await getSquadsOfMatch(query.matchId);
  console.log('3');
}
ctx.send(squadList);
      }

I have used console.log() to see the execution order. The order I want is 1 2 3 but the actual output is 3 1 2 How can I make the program to execute these lines in the last. squadList = await getSquadsOfMatch(query.matchId); console.log('3');

Tavinder Singh
  • 380
  • 1
  • 7
  • 17

2 Answers2

2

You cannot use async function with forEach if we mimic what forEach does it will be:

function forEach(arr, callback){
   for(let i=0;i<arr.length;i++){
        callback(arr[i], i, arr);
   }
}

As you can see, it doesn't await your async callback.

You can create a custom forEach like:

async function forEach(arr, callback){
   for(let i=0;i<arr.length;i++){
        await callback(arr[i], i, arr);
   }
}

Or use simple for loop.

Also, what you can do is push all the promises to an array and call Promise.all to process all the requests.

async (ctx) => {
    var query = ctx.request.query;
    var squadList = await getSquadsOfMatch(query.matchId);
    if (squadList.length <= 1) {
        var response = await axios.get(
            `${strapi.config.currentEnvironment.getSquadListApi}?apikey=${strapi.config.currentEnvironment.cricApiKey}&unique_id=${query.matchId}`
        );

        squadList = response.data.squad;

        var match = await Match.findOne({
            unique_id: query.matchId
        });

        var team1Squad, team2Squad;
        const promises = squadList.map(squad => {
            if (squad.name === match['team-1']) {
                team1Squad = {
                    name: match['team-1'],
                    match_id: match['unique_id'],
                    match: match['_id'],
                };
                console.log('1');
                return new Squad(team1Squad).save(); //returning the promise
            } else if (squad.name === match['team-2']) {
                team2Squad = {
                    name: match['team-2'],
                    match_id: match['unique_id'],
                    match: match['_id'],
                };
                console.log('2');
                return new Squad(team2Squad).save(); //returning the promise
            }
        });
        await Promise.all(promises); //making all the changes parallely

        squadList = await getSquadsOfMatch(query.matchId);
        console.log('3');
    }
    ctx.send(squadList);
}

NOTE: I have made one article that covers loops and async functions, feel free to check it out, https://medium.com/trappedpanda/loops-asynchronous-functions-and-returning-collective-results-in-node-js-b7566285fb74

Aritra Chakraborty
  • 12,123
  • 3
  • 26
  • 35
0

You can create an array of promises that have to be executed first and wait for them to resolve using Promise.all before running getSquadsOfMatch:

getSquadList: async (ctx) => {
    var query = ctx.request.query;
    var squadList = await getSquadsOfMatch(query.matchId);
    if (squadList.length <= 1) {
      var response = await axios.get(
        `${strapi.config.currentEnvironment.getSquadListApi}?apikey=${strapi.config.currentEnvironment.cricApiKey}&unique_id=${query.matchId}`
      );

      squadList = response.data.squad;

      var match = await Match.findOne({
        unique_id: query.matchId
      });

      var team1Squad, team2Squad;

      const tasks = squadList.map(async squad => {
        if (squad.name === match['team-1']) {
          team1Squad = {
            name: match['team-1'],
            match_id: match['unique_id'],
            match: match['_id'],
          };

          await new Squad(team1Squad).save();
          console.log('1');
        } else if (squad.name === match['team-2']) {
          team2Squad = {
            name: match['team-2'],
            match_id: match['unique_id'],
            match: match['_id'],
          };

          await new Squad(team2Squad).save();
          console.log('2');
        }
      });

      await Promise.all(tasks)
      squadList = await getSquadsOfMatch(query.matchId);
      console.log('3');
    }
    ctx.send(squadList);
  }
antonku
  • 7,377
  • 2
  • 15
  • 21