Search code examples
javascriptnode.jses6-promise

How to wait for the final result of a for loop with API calls?


This loop is going to run an arbitrary amount of times, and I want to get the result out of it after them all. Anything I try (promisifying, async/await, nesting functions, et al) seems to be a dead end. I don't get why I cannot just stick a .then on the API call, or on the function I made here. But I suspect the problem is more fundamental with my understanding, because I can't seem to even get just the "data" to return...same inability to wait on the API call. Wrapping it in a promise loses the "data" and pulling it with the "for loop" inside there doesn't work either. This is making me question my entire progress with JS/implementing other people's APIs.

  const gotPeeps = () => {
      challongeClient.tournaments.show({
      id: tournamentURL,
      callback: (err, data) => {
         //return data //doesnt return "data" from gotPeeps?
        for (const [key, value] of Object.entries(data.tournament.matches)) {
            if (value.match.state === 'open') {
              peepsList.push(value.match.player1Id, value.match.player2Id)
              console.log(peepsList)
    }}}})}
    gotPeeps()

EDIT To the comments: I'm trying to get the results after the for loop is complete. The "loop" I was referring to is the "for of" over the data Object. "Putting the code after the loop but inside the callback" does not work. I have a previous question in my week of failing to solve this: How to solve race condition in Javascript? Here is the whole thing, with some past versions commented out.:

const tournamentModel = require('../models/tournamentSchema')
require('dotenv').config()
const challonge = require('challonge');

module.exports = {
  name: 'getmatches',
  aliases: ['gm'],
  cooldown: 0,
  description: 'Get Challonge data into console.',
 
  execute(message, args, cmd, client, Discord, profileData) {
    let peep = ''
    let peepsList = ''
    const tournamentURL = 'TESTING_Just_Sign_Up_If_You_See_This850587786533011496'
    const challongeClient = challonge.createClient({
      apiKey: process.env.CHALLONGE_API_KEY,
    })
  
  const getPlayer = (playerXId) => {
    return new Promise((resolve, reject) => {
      challongeClient.participants.show({
        id: tournamentURL,
        participantId: playerXId,
        callback: (err, data) => {
          if (err) {
            reject(err);
            return;
          }        
          peep = data.participant.misc
          peepsList.push(peep)
          console.log(peepsList)
          console.log('RUNNING GET PLAYER', playerXId, playerIndexCount)
          resolve(peepsList);  
          }
        });
      });
    }
    
    

    const peepsList = []
    const matchList = []
    const gotPeeps = () => {
      challongeClient.tournaments.show({
      id: tournamentURL,
      include_participants: 1,
      include_matches: 1,
      callback: (err, data) => {
        for (const [key, value] of Object.entries(data.tournament.matches)) {
            if (value.match.state === 'open') {
              peepsList.push(value.match.player1Id, value.match.player2Id)
              console.log(peepsList)
            }
          }
      }
        
              /*// GET PLAYERS
            getPlayer(value.match.player1Id)
            .then(() => {
            getPlayer(value.match.player2Id)
          }) 
        }
          */
                    
                  }
            )         
      }
      
    gotPeeps()
    }}

Solution

  • You can make this function return a promise and await the function (as long as your function is an async function)

    const gotPeeps = () => {
      return new Promise((resolve, reject) => {
        const peepsList = []; // declare the empty array to e filled
    
        challongeClient.tournaments.show({
          id: tournamentURL,
          callback: (err, data) => {
            for (const [key, value] of Object.entries(data.tournament.matches)) {
              if (value.match.state === "open") {
                peepsList.push(value.match.player1Id, value.match.player2Id);
              }
            }
            resolve(peepsList); // resolve the promise with the filled array
            // TODO: handle reject
          },
        });
      })
    };
    
    (async () => {
      try {
        const result = await gotPeeps();
      } catch (error) {
        // TODO: handle error
      }
    })();