简体   繁体   English

等待 api 响应处理完再迭代 for 循环

[英]Wait for api response to be processed before iterating for loop

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我正在尝试编写一个 Discord 机器人,它基本上使用 HTTP 请求检查每个 Discord 用户是否在会员数据库中具有有效会员资格(尚未过期)所以我写了如下内容

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.这在检查一个成员资格时有效,但是当我开始引入其他成员资格时,我注意到 for 循环在我什至还没有得到第一个成员资格的响应之前就已经完成,此时不再定义成员资格。

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?我怎样才能更改上面的代码,以便 for 循环在执行下一次迭代之前等待 HTTP 响应被处理?

I would use await fetch() to make sure the API response is completed before you can do anything with the data.我会使用await fetch()来确保 API 响应已完成,然后您才能对数据执行任何操作。 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.因此,在您的情况下,您应该更改您的代码,以便您的 await fetch 首先在循环之外完成,这与您现在的方式相反。 Here is a really good article on how to use Await Fetch.这是一篇关于如何使用 Await Fetch 的非常好的文章。

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

Await in the loop will make the checks sequentially.在循环中等待将按顺序进行检查。 If they don't depend on one another, run the checks concurrently with Promise.all.如果它们不相互依赖,则与 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
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM