Переходите к следующей итерации forEach после разрешения обещания - PullRequest
1 голос
/ 03 октября 2019

Я собираюсь обработать массив некоторых данных, и на каждой итерации я имею дело с обещанием.

Я хочу перейти к следующей итерации forEach, только когда обещание на текущей итерации выполненорешен.

Я искал различные решения и понял, что использование for(... of ...) вместо forEach может помочь. Но до сих пор не могу понять это.

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

Ответы [ 4 ]

2 голосов
/ 03 октября 2019

Похоже, что никто еще не опубликовал конкретную асинхронную / ожидающую, так что вот как вы используете ее для… 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;
  }

  // …
}

Все это находится внутри асинхронной функции. (Кроме того, { ...params } немного странно. Что не так с params напрямую?)

2 голосов
/ 03 октября 2019

Если вы можете, я бы порекомендовал легкий для чтения и понимания цикла с await / async. Обратите внимание на то, что верхний уровень await является очень недавним дополнением, поэтому вы должны обернуть его в некоторую асинхронную функцию (что вы, вероятно, все равно сделаете).

Если вы не можете использовать async / await, вы можете использовать reduce сПервоначально разрешенное обещание связывает последующие вызовы.

Обратите внимание , что я использовал функцию sleep, которая разрешает обещание через некоторое время. Звонок на sleep должен быть взаимозаменяем с вызовами Axios.

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);
2 голосов
/ 03 октября 2019

Рекурсия помогает:

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)
0 голосов
/ 03 октября 2019

Просто используйте await для вызова API.

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

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

      const response = await axios.post('/fruits', { ...params })
    });
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...