Home > Mobile >  Make an async function execution wait after the 4th call
Make an async function execution wait after the 4th call

Time:09-23

I am using fetch to make API calls to a 3rd party API. I have multiple access tokens to help prevent me from reaching their rate limit. The problem I am having is that the loop isn't working properly. After the initial loop, only the 2nd key in the array is called and therefore hits the API limit.

Here is the code:

// outside of function scope for keeping track of which key to use
let count = -1;

export default async function apiCall(
  request_type: string,
  url: string,
  request_body?: RequestInit,
  headers?: HeadersInit
) {
  const keys: string[] = [
    `${env.API_KEY_0}`,
    `${env.API_KEY_1}`,
    `${env.API_KEY_2}`,
    `${env.API_KEY_3}`,
  ];

  if (count === 4) {
    await wait(5);
    count = 0;
  }

  const request: RequestInit = {
    method: request_type,
    headers: headers
      ? headers
      : {
          "Content-Type": "application/json",
          "Access-Token": `${keys[count]}`,
        },
  };

  if (request_type !== "GET" && request_type !== "DELETE") {
    request.body = JSON.stringify(request_body);
  }

  // used to switch the tokens to prevent rate_limiting. Faster than using a rate limiter in each function
  count  ;

  console.log(keys[count]);
  // return await fetch(`https://api.com/${url}`, request)
  //   .then((result) => {
  //     return result.json();
  //   })
  //   .catch((error) => {
  //     console.log(error);
  //   });
}

const wait = (seconds = 1) => {
  new Promise((r) => setTimeout(r, seconds * 1e3));
};

And here is the console output showing me it's not waiting after the 4th function call:

API_KEY_1
API_KEY_2
API_KEY_3
undefined
API_KEY_1
API_KEY_1
API_KEY_1
API_KEY_1
API_KEY_1
...

EDIT

Part of the problem was the wait function not returning, but even after the wait function call is done, it doesn't reset properly as shown in the console.log here:

API_KEY_1
API_KEY_2
API_KEY_3
undefined
Waiting...
API_KEY_1
API_KEY_1
API_KEY_1
API_KEY_1
API_KEY_1
...

Here's a playground that will give better insight to what I am seeing: https://playcode.io/968433

The desired outcome is:

API_KEY_1
API_KEY_2
API_KEY_3
API_KEY_4
Waiting...
API_KEY_1
API_KEY_2
API_KEY_3
API_KEY_4
Waiting...
...

CodePudding user response:

That's because you didn't return the Promise from your wait function. Try this:

const wait = (seconds = 1) => new Promise((r) => setTimeout(r, seconds * 1e3));

CodePudding user response:

If you want to reliably loop through those API keys and wait briefly when you wrap around, start with count = -1 as you are when you first create it:

// (No change so far)
let count = -1;

There's also probably no reason you should recreate your array every time, so outside the function next to count (there's also no reason for `${env.API_KEY_0}` and such unless you have to convert from something to string, which seems unlikely just use env.API_KEY_0 or String(env.API_KEY_0) if you need that conversion):

const keys: string[] = [
    env.API_KEY_0,
    env.API_KEY_1,
    env.API_KEY_2,
    env.API_KEY_3,
];

Then, at the beginning of your function:

if (  count === 4) {
    await wait(5);
    count = 0;
}

...and remove any other code that changes count.

Then use "Access-Token": keys[count] in the request (again no need for the template literal).

  • Related