Home > other >  Wait for api response to be processed before iterating for loop
Wait for api response to be processed before iterating for loop

Time:02-21

I'm trying to write a Discord bot that basically checks if each Discord User has a valid membership (that hasn't expired) inside a membership database using HTTP requests so I wrote something like the following

function checkmemberships() {

    const memberships = fs.readFileSync('emailtest.txt').toString().toLowerCase().replace(/(?:\\[rn]|[\r\n] ) /g, " ").split(" ");

    const tenantId = 'example';
    var today = new Date().toISOString().slice(0, 10);

    for (i = 0; i < memberships.length; i  = 3)
    {

        let contactId = memberships[i];
        const membershipnumber = memberships[i   1];
        fetch(`https://rolodex.api.rhythmsoftware.com/contacts/${tenantId}/number/${contactId}`,
                {
                    method: 'GET',
                    headers: {
                        'Content-Type': 'application/json',
                        'Authorization': global.apikey //this is generated somewhere else
                    },
                }
        )
                .then((res) => res.json())
                .then((res) => {
                    if (res.errorMessage == "RecordNotFound: Could not find a contact with the supplied number")
                    {
                        //Still To Do but not important
                    } else
                    {
                        if (res.id)
                        {
                            contactId = res.id; //Number can actually be different from what the user originally posts
                            fetch(`https://membership.api.rhythmsoftware.com/memberships/${tenantId}/contact/${contactId}`,
                                    {
                                        method: 'GET',
                                        headers: {
                                            'Content-Type': 'application/json',
                                            'Authorization': global.apikey
                                        },
                                    }
                            )
                                    .then((resp) => resp.json())
                                    .then((resp) => {
                                        console.log(resp);
                                        if (resp.expiration_date)
                                        {
                                            let guild = client.guilds.cache.get('890266470641201172');
                                            let member = guild.members.cache.get(membershipnumber); //At this point the membership isn't found because at this point it's undefined
                                            if (resp.expiration_date <= today) {
                                                member.roles.remove("890270511261696031");
                                                member.roles.remove("890270660239175700");
                                            }

                                        }
                                    })
                        }
                    }
                })
    }
}

This works when checking one membership but when I start introducing other memberships, I notice that the for loop is being completed before I have even got a response back for the first membership at which point then membershipnumber is no longer defined.

How can I change the code above so that the for loop waits for the HTTP response to be processed before it then does the next iteration?

CodePudding user response:

I would use await fetch() to make sure the API response is completed before you can do anything with the data. This will prevent you from working with the data before the response is even complete.

So, in your case, you should change your code so that your await fetch is done first and outside of the loop, which is the opposite of how you have it now. Here is a really good article on how to use Await Fetch.

https://dmitripavlutin.com/javascript-fetch-async-await/#2-fetching-json

CodePudding user response:

Await in the loop will make the checks sequentially. If they don't depend on one another, run the checks concurrently with Promise.all.

function checkmemberships() {
    const memberships = fs.readFileSync('emailtest.txt').toString().toLowerCase().replace(/(?:\\[rn]|[\r\n] ) /g, " ").split(" ");

    const tenantId = 'example';
    var today = new Date().toISOString().slice(0, 10);

    let promises = [];
    for (i = 0; i < memberships.length; i  = 3) {
        let contactId = memberships[i];
        const membershipnumber = memberships[i   1];
        promises.push(checkMembership(tenentId, membershipnumber, today);
    }
    return Promise.all(promises);
}


function checkMembership(tenentId, membershipnumber, today) {
  // .... from the op
  return fetch(`https://rolodex.api.rhythmsoftware.com/contacts/${tenantId}/number/${contactId}`, // ...
    // .then do json parse
    // .then do expiration check
      // return something, like a bool if the member is in good standing
}
  • Related