简体   繁体   中英

NodeJS wait for loop to finish (async / await / promisse)

I'm trying to make a loop fetching some info in an API, first I need this loop for to wait for the request to finish and after continue for the next array value, after the loop finish, then I need it to call that function again every 5 seconds, but only after the previous call ends.

Something like this:

let ids = [1, 2];

async function getInfoAPI(ids) {

   for (const id of ids){
      const apiInfo = await fetch(`https://apiurl/${id}`);
      const infoJSON = await apiInfo.json();

      //Do more things here
   }
}

Now I need to call the function and wait for the loop to finish. After the loop is completed then wait for 5 seconds and call the getInfoFromAPI function again. I tried setInterval but if the loop, for some reason, takes more than 5 seconds to respond, the getInfoFromAPI will be called again even if it didn't finish the previous loop.

setInterval(function(){ 
        getInfoAPI(ids);
}, 5000);

Is there any way I could do that using promises or something like that?

Thanks

You can do something like this:

function run() {
    getInfo(...).then(() => {
        setTimeout(run, 5000)
    });
}

run().catch(err => {
   console.log(err);
});

Or, I prefer using a promise version of setTimeout() . I the latest version of nodejs, you can use timersPromises.setTimeout() and it returns a promise:

import { setTimeout } from 'timers/promises';

async function run() {
    await getInfo(...)
    await setTimeout(5000);
    return run();
}

run().catch(err => {
   console.log(err);
});

Or, use a while loop with await :

import { setTimeout } from 'timers/promises';

async function run() {
    while (true) {
        await getInfo(...)
        await setTimeout(5000);
    }
}

run().catch(err => {
   console.log(err);
});

You can achieve this by importing the promise based setTimeout that ships with NodeJs 16+ and using it as follows:

Import:

import { setTimeout } from "timers/promises"

Use:

while (true) {
  await getInfoAPI(ids);
  await setTimeout(5000);
}

Use recursion:

async function getInfoPeriodically() {
  await getInfoAPI(ids);
  setTimeout(() => {
    getInfoPeriodically()
  }, 5000);
}

You can add the parameters to customize this function/pass values in but this is the idea.

Why don't you try to use Promise.all or Promise.allSettled ? With that you can use concurrency to fetch all the data at once, instead that one by one. In case you need to do it one by one, I suggest you to use for-await...of .

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