Search code examples
javascriptarraysjsonasynchronous

Is there a way to to use each value of an array as a function parameter and then store each result in another array or object?


so i have a function that returns array of matchIds. And i have a function that returns object of data from the macth based on the matchID

async function getMatchData(matchId){
    const response = await fetch(`https://europe.api.riotgames.com/lol/match/v5/matches/${matchId}?api_key=`+key);
    var data = await response.json();
    let matchData= {
        teams: data.info.teams.map(element => team = { teamid: element.teamId, win: element.win }),
        players: data.info.participants.map(element => obj = { team: element.teamId, champ: element.championName, champIcon: element.championName + '_0.jpg', summoner: element.summonerName, level: element.champLevel, build: { item1: element.item1, item2: element.item2, item3: element.item3, item4: element.item4, item5: element.item5, item6: element.item6, item0: element.item0 }, kills: element.kills, deaths: element.deaths, assists: element.assists, kda: (element.kills + element.assists) / element.deaths, cs: element.totalMinionsKilled + element.neutralMinionsKilled, victory: element.win })
    }
   return matchData

now i want to use each matchId from the matchIds array as a parameter in the getMatchData function and put each response in an array or object

i tried to run thru the array with map but it returns [ Promise { }, Promise { }, ... ] and says: Cannot read properties of undefined (reading 'teams')

let matchHistoryData= matches.map(element=>getMatchData(element))
     console.log(matchHistoryData);  

matches being the array of matchIds


Solution

  • Your question changed, so here is the answer to the updated question:

    As getMatchesData is an async function, it is guaranteed to return a promise object. By consequence, the .map() call is bound to return an array of promises.

    As these promises will only resolve in some future -- when these await-ed promises resolve, and matchData assignments get executed -- you'll need to listen in with asynchronous code to be executed when they do. You can use Promise.all for this:

    Promise.all(matches.map(element=>getMatchData(element)))
           .then(matchHistoryData => {
               console.log(matchHistoryData);
           });
    

    Note that any other code that needs matchHistoryData will need to run inside that then callback, or else be called from there (or be chained in yet another then callback,...).

    Addendum

    In comments you have presented code that wraps the code in a logData function. This doesn't take away the fact that the response data is only available in the future, so logData cannot possibly return that future data now. You have to stick with the asynchronous way of programming, and have your code executed in the future, when the promise resolves:

    async function logData(sum){
        let name = sum;
        let puuid = await getPUUID(name);
        let matches = await getMatchIds(puuid);
        return Promise.all(matches.map(element => getMatchData(element)));
    }
    
    logData('ΤhePrideStalker').then(matchHistoryData => {
        console.log(matchHistoryData);
        /*
        All code that needs the values in matchHistoryData should
        be placed within this callback -- not outside of it.
        
        ...your code comes here...
        */
    });
    
    /* No code comes here that needs the results, because the results are not there yet */