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

Time:06-06

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

CodePudding user response:

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);
});

CodePudding user response:

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.

CodePudding user response:

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);
}

CodePudding user response:

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.

CodePudding user response:

const delay = (ms) => new Promise(ok => setTimeout(ok, ms))

async function go(){
  await getInfoAPI(ids)
  await delay(5000)
  await getInfoAPI(ids)
}
  • Related