Sergey
Sergey

Reputation: 1075

Go to the next forEach iteration after promise resolves

I'm going throgh the array of some data and on every iteration I deal with promise.

What I want is to go to the next forEach iteration only when the promise on the current iteration is resolved.

I searched through out different solutions and figured out that usage of for(... of ...) instead of forEach could make the trick. But still can't figure it out.

const data = ['apple', 'orange', 'banana'];

data.forEach((row, rowIndex) => {
  let params = {
    fruitIndex: rowIndex,
  };

  axios.post('/fruits', { ...params })
    .then(response => {
      // go to the next iteration of forEach only after this promise resolves
    })
    .catch(error => console.log(error))
});

Upvotes: 1

Views: 550

Answers (4)

Ricardo Araújo
Ricardo Araújo

Reputation: 155

Just use await on the api call.

function postFruitData(){
    const data = ['apple', 'orange', 'banana'];

    data.forEach(async (row, rowIndex) => {
      let params = {
        fruitIndex: rowIndex,
      };

      const response = await axios.post('/fruits', { ...params })
    });
}

Upvotes: -1

Ry-
Ry-

Reputation: 224932

It looks like nobody posted the specific async/await yet, so this is how you use it with for…of:

const data = ['apple', 'orange', 'banana'];

for (const [rowIndex, row] of data.entries()) {
  let params = {
    fruitIndex: rowIndex,
  };

  let response;

  try {
    response = await axios.post('/fruits', { ...params });
  } catch (error) {
    console.log(error);
    continue;
  }

  // …
}

This all being placed inside an async function. (Also, { ...params } is a bit weird. What’s wrong with params directly?)

Upvotes: 2

Phillip
Phillip

Reputation: 6253

If you can, i'd recommed an easy to read and understand for of loop with await/async. Notice the top level await is very recent addition, so you should wrap that in some async function (which you'd likely do anyway).

If you cannot use async/await you can use reduce with an initial resolved promise to chain subsequent calls.

Notice that I used a function sleep that resolves a promise after some time. The call to sleep should be interchangeable with axios calls.

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

const data = [1000, 2000, 3000];


function withReduce() {
  console.log('Sequential Promises with Reduce:');

  return data.reduce((previousPromise, ms) => {
    return previousPromise
      .then(() => {
        console.log(`sleeping for ${ms}ms`);
        return sleep(ms);
      });
  }, Promise.resolve());
}

async function withAsync() {
  console.log('Sequential Promises with for of and await:');

  for (let ms of data) {
    console.log(`sleeping for ${ms}ms`);
    await sleep(ms);
  }
}

withReduce().then(withAsync);

Upvotes: 2

ISD
ISD

Reputation: 1012

Recursion helps:

const data = ['apple', 'orange', 'banana'];


function request_fruit(n) {
  let params = {
    fruitIndex: n,
  };

  axios.post('/fruits', { ...params })
    .then(response => {
      // Work with recived...
      // ....
      // Request next
      if(n+1<fruits.length) request_fruit(n+1)
    })
    .catch(error => console.log(error))
};
request_fruit(0)

Upvotes: 3

Related Questions