Skip to content Skip to sidebar Skip to footer

NodeJS: Async Loop That Waits Between Iterations

I'm trying to make some checks before saving an array of objects (objects[]) to the DB (mongoDB using mongoose): Those objects are already sorted by date, so objects[0].date is lo

Solution 1:

const myArray = ['a','b','c','d'];

async function wait(ms) { // comment 3
  return new Promise(resolve => setTimeout(resolve, ms));
}

async function doSomething() {
  await myArray.reduce(async (promise, item) => {
    await promise; // comment 2
    await wait(1000);

    // here we could await something else that is async like DB call
    document.getElementById('results').append(`${item} `);
  }, Promise.resolve()); // comment 1
}


setTimeout(() => doSomething(), 1000);
<div id="results">Starting in 1 second <br/></div>

You can also use reduce and async await which you already said you've tried.

Basically, if you read how reduce works you can see that it accepts 2 parameters, first being callback to execute over each step and second optional initial value.

In the callback we have first argument being an accumulator which means that it accepts whatever the previous step returns or the optional initial value for first step.

1) You are giving initial value of promise resolve so that you start your first step.

2) Because of this await promise you will never go into next step until previous one has finished, since that is the accumulator value from previous step, which is promise since we said that callback is async. We are not resolving promise per say here, but as soon as the previous step is finish, we are going to implicitly resolve it and go to next step.

3) You can put for example await wait(30) to be sure that you are throttling the Ajax requests and not sending to many requests to 3rd party API's, since then there is no way that you will send more than 1000/30 requests per second, even if your code executes really fast on your machine.


Solution 2:

Hm, ok i am not 100% sure if i understand your question in the right way. But if you try to perform an async array operation that awaits for your logic for each item, you can do it like follow:

async loadAllUsers() {
    const test = [1,2,3,4];
    const users = [];
    for (const index in test) {
      // make some magic or transform data or something else
      await users.push(test[index])
    }

    return users;
  }

Then you can simply invoke this function with "await". I hope that helps you.


Solution 3:

In asyncForEach function you are resolving a Promise, setTimeout doesn't return a Promise.So if you convert your setTimeout to Promise. It will work as expected. Here is the modified code:

testArray.asyncForEach(function(element) {
 return new Promise((resolve, reject) => {
  setTimeout(() => {
   console.log(element);
   return resolve(element)
 }, Math.random() * 500);
})
});

Post a Comment for "NodeJS: Async Loop That Waits Between Iterations"