简体   繁体   中英

Using setTimeout to pause rest API calls

I have an array of IDs and a fix endpoint that I need to call. So I want to foreach the array of IDs and make a corresponding rest API call for each ID. Since I don't want to "flood" the endpoint, I want to wait a second between each call. Also, I'd like to wait for the response before calling endpoint with a new ID.

Here's what I came up with:

// Code goes here
console.clear();

const url = 'some-domain.com/v1/api/users';
const ids = [1, 2, 3, 4, 5, 6, 7];
const serviceMock = (id) => new Promise((resolve, reject) => {

  console.log('Got request for id ' + id);
  setTimeout(() => {

    resolve(`${url}${id} returned ${ Math.floor((Math.random() * 100) + 1)}`);
  }, 2000);
});

const main = async() => {

  let index = 0;
  for (let id of ids) {

    index++;
    setTimeout(async() => {

      const data = await serviceMock(id);
      console.log(`Done for user ${id}!`);
      console.log(data);
    }, 1000 * index);
  }
};

main();

The setTimeout in serviceMock is used to simulate the rest API call, and the setTimeout in main is used to pause between the calls.

Now, how I would like it to behave is as follows (in console):

Got request for id 1
Done for user 1!
some-domain.com/v1/api/users1 returned 77
Got request for id 2
Done for user 2!
some-domain.com/v1/api/users2 returned 75
Got request for id 3
Done for user 3!
some-domain.com/v1/api/users3 returned 26
Got request for id 4
Done for user 4!
some-domain.com/v1/api/users4 returned 44
Got request for id 5
Done for user 5!
some-domain.com/v1/api/users5 returned 79
Got request for id 6
Done for user 6!
some-domain.com/v1/api/users6 returned 52
Got request for id 7
Done for user 7!
some-domain.com/v1/api/users7 returned 34

This is what I get:

Got request for id 1
Got request for id 2
Got request for id 3
Done for user 1!
some-domain.com/v1/api/users1 returned 77
Got request for id 4
Done for user 2!
some-domain.com/v1/api/users2 returned 75
Got request for id 5
Done for user 3!
some-domain.com/v1/api/users3 returned 26
Got request for id 6
Done for user 4!
some-domain.com/v1/api/users4 returned 44
Got request for id 7
Done for user 5!
some-domain.com/v1/api/users5 returned 79
Done for user 6!
some-domain.com/v1/api/users6 returned 52
Done for user 7!
some-domain.com/v1/api/users7 returned 34

Here's a working example: http://plnkr.co/edit/sNfk8GIfqbhrpql5hQ16?p=preview

what exactly am I missing here?

Don't put 'await' in setTimeout.

I suggest you write wait function:

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

Now you can easily type:

const main = async () => {

  let index = 0;
  for (let id of ids) {
    index++;

    await wait(1000);

    const data = await serviceMock(id);
    console.log(`Done for user ${id}!`);
    console.log(data);
  }

};

main();

A simple recursive solution: create a variable var i = 0 to hold the current index of your ID array. Next create a function x() that makes your API call. In the success function of your API call, increment i ie the current index of your ID array, then do a check i == array.length if true do nothing if false call function x() again.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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