Home > OS >  How to create a timer with each iteration of making an api call based on list
How to create a timer with each iteration of making an api call based on list

Time:11-10

I have a javascript array that contains 40 items in it. I want to create a function so that the function cycles through of item in the array and makes an api call based on the current value of the array.

The catch is that I want there to be a 3 second timer between each of the api calls in order to prevent exceeding the number of allows api calls per second.

This function gets the list of properties in an array. This is what I attempted so far.

const getPropertiesInCity = (properties) => {
  for(i = 0; i < properties.length; i  ){
    let property = properties[i]
    setTimeout(() => {
      getPropertyDetails(property.zpid)
    }, 5000)
  }
}

what I get is this:

error
error
error
error
error
error
error
error
error
error
error
error
error
error
error
error
error
error
error
error
error
error
error
error
error
error
error
error
error
error
error
error
error
error
error
error
error
have the property
have the property
have the property

the error is because I am sending to many request within a specific time. It waits 5 seconds and the gives me all the errors and then 3 positive responses.

CodePudding user response:

Your code is just scheduling all the API calls to run in 5 seconds. It isn't spacing them apart at all because setTimeout() is non-blocking so the whole for loop runs immediately. You can run one call each 3 seconds, by just incrementing the timer value each time in the loop.

const getPropertiesInCity = (properties) => {
  for(let i = 0; i < properties.length; i  ){
    let property = properties[i]
    setTimeout(() => {
      getPropertyDetails(property.zpid)
    }, i * 3000)
  }
}

You can also just start the next iteration with a timer within the loop like this:

const getPropertiesInCity - (properties) => {
    let i = 0;
    function run() {
        if (i < properties.length) {
            getPropertiesDetails(properties[i  ].zpid);
            // schedule next iteration of the loop
            setTimeout(run, 3000);
        }
    }
    run();
}; 

If getPropertiesDetails() returns a promise or takes a completion callback, you can also start the next iteration (with a timer) when it completes rather than when you call it.

CodePudding user response:

Using iter-ops library (I'm the author):

import {pipeAsync, map, wait, delay} from 'iter-ops';

const properties = [...]; // your list of objects

const i = pipeAsync(
    properties,
    map(p => getPropertyDetails(p.zpid)), // re-map into requests
    wait(), // wait for the request to finish
    delay(5000) // wait for 5 seconds
); //=> AsyncIterable

// to handle all iteration errors:
i.catch(err => {
    console.log('CAUGHT:', err);
});

(async function () {
    for await (const a of i) {
        console.log(a); // whatever getPropertyDetails resolves with
    }
})();

In addition, the example above gives you all the results produced by each getPropertyDetails call, plus handles all errors in one place.

  • Related