Korih
Korih

Reputation: 13

set timer inside a loop for graphql query

The thing I'm doing here is fetching anime characters from anilist graphql api. The reason I've added a loop is so I could fetch data from a certain character id to a limit. For example 1-100. But I want to respect their API rate limits and so I'd like a way to limit my requests to 1 per second. Hence, I've used setTimeout, but I still got rate-limited from the API and using setInterval only keeps on looping it every 5 seconds. Like the same data gets fetched every 5 seconds. Is there any way I can make it as I've mentioned?

My code:

const fs = require("fs");
const number = 3;
const axios = require("axios");

async function fetchData() {
  for (let i = 1; i <= number; i++) {
    const query = axios
      .post(
        "https://graphql.anilist.co",
        {
          query: `query character(
                    $id: Int
                    $page: Int
                    $sort: [MediaSort]
                    $onList: Boolean
                    $withRoles: Boolean = false
                  ) {
                    Character(id: $id) {
                      id
                      name {
                        first
                        middle
                        last
                        full
                        native
                        userPreferred
                        alternative
                        alternativeSpoiler
                      }
                      image {
                        large
                      }
                      favourites
                      isFavourite
                      isFavouriteBlocked
                      description
                      age
                      gender
                      bloodType
                      dateOfBirth {
                        year
                        month
                        day
                      }
                      media(page: $page, sort: $sort, onList: $onList) @include(if: $withRoles) {
                        pageInfo {
                          total
                          perPage
                          currentPage
                          lastPage
                          hasNextPage
                        }
                        edges {
                          id
                          characterRole
                          voiceActorRoles(sort: [RELEVANCE, ID]) {
                            roleNotes
                            voiceActor {
                              id
                              name {
                                userPreferred
                              }
                              image {
                                large
                              }
                              language: languageV2
                            }
                          }
                          node {
                            id
                            type
                            isAdult
                            bannerImage
                            title {
                              userPreferred
                            }
                            coverImage {
                              large
                            }
                            startDate {
                              year
                            }
                            mediaListEntry {
                              id
                              status
                            }
                          }
                        }
                      }
                    }
                  }`,
          variables: {
            id: i,
            withRoles: false,
          },
        },
        {
          headers: {
            "Content-Type": "application/json",
          },
        }
      )
      .then((response) => {
        // console.log(response.data.data.Character)
        const jsonContent =
          JSON.stringify(response.data.data.Character, null, 4) + ", ";

        fs.appendFile("./chars.json", jsonContent, function (err) {
          if (err) {
            return console.log(err);
          }

          console.log("The file was saved!");
        });
      })
      .catch((error) => console.log(`Code: ${error}`, error));
  }
}

fetchData();

Upvotes: 1

Views: 404

Answers (1)

Sergey Sosunov
Sergey Sosunov

Reputation: 4600

Something like that will work for you (Asuming all the rest was ok):

const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

async function fetchData() {
  for (let i = 1; i <= number; i++) {
    // So in case your function is called in loop - request will be delayed
    await delay(5000); // TODO: Change to whatever you need
    const query = axios.post(
      "https://graphql.anilist.co",
      {
        query: someQuery, // TODO: Set your query here
        variables: { id: i, withRoles: false }
      },
      {
        headers: { "Content-Type": "application/json" }
      }
    );

    try {
      const response = await query;
      const jsonContent = JSON.stringify(response.data.data.Character, null, 4) + ", ";

      fs.appendFile("./chars.json", jsonContent, function (err) {
        if (err) {
          return console.log(err);
        }
        console.log("The file was saved!");
      });
    } catch (e) {
      console.log(`Code: ${e}`, e);
    }
  }
}

Upvotes: 1

Related Questions