Выполнять асинхронные действия полусинхронно в Axios - PullRequest
0 голосов
/ 14 октября 2019

У меня есть следующий код:

   * Fetch stats from api
   */
  fetchStats() {
    this._isFetching = true;
    // fetch stats after building url and replacing invalid characters
    return new Promise(async (resolve, reject) => {
      await API.fetchStats(this.rsn)
        .then(jres => {
          this.skills = jres.main.skills;
          this._isFetching = false;
          resolve('success');
        })
        .catch(err => {
          console.log(err);
          console.log('error retreiving stats');
          this._isFetching = false;
          reject('Failed to retreive stats');
        })
        .finally(() => {
          this._isFetching = false;
        });
    });
  }

Я думал, что асинхронный с ожиданием заставит его ждать, пока он не получит ответ, прежде чем продолжить. Возвращение обещания - это то, что я добавил в тестирование, чтобы посмотреть, смогу ли я сделать его синхронным.

Тогда мой код, который использует этот метод:

memberCollection.forEach(async el => {
        await el.player.fetchStats()
        .then(() => {
          console.log(`Refreshed ${el.player.rsn}'s account`);
        })
        .catch(console.log(`Failed to refresh ${el.player.rsn}'s account`));
});

Я думал, что он подождет, пока не получит ответ, а затем console.log будет либо успешное обновление, либо неудачное обновление. Вместо этого я вижу целую кучу «успешных» сообщений, за которыми следует строка с ошибочными сообщениями, указывающими на то, что он выполняет и сообщения then, и сообщение catch в foreach. Кто-нибудь знает, как я могу сделать эту работу.

Моя проблема в том, что Axios не работает по тайм-ауту (я предполагаю, что это связано с количеством отправляемых запросов и тем, что есть 5-10 секундзадержка при извлечении из базы данных), если я перехожу к URL-адресу API вручную, он работает так же, как если бы я просто использовал один элемент (в отличие от forEach), он работал нормально. Поэтому я пытаюсь ограничить количество сработавших запросов одновременно. Я попытался установить тайм-аут моего axios на 10, 20 и 60 секунд, но это не улучшило ситуацию.

Код решения:

const asyncForEach = async (arr, cb) => {
  for(let i=0;i<arr.length;i++) {
    let el = arr[i];
    try {
      let res = await cb(el);
    } catch (err) { console.log(err) };

    if(el.player && el.player.rsn) console.log(`Processed ${el.player.rsn}`);
  }
  console.log('done processing in asyncForEach');
}

1 Ответ

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

не связано с axios, но с async await.

рассмотрим

function slow(i){
    return new Promise((ok,ko)=>{
        return setTimeout(_=>ok(i), 1000)
    })
}
async function asyncForEach(arr, cb){
    for(var i = 0; i<arr.length; ++i){
        let el = arr[i];
        let res = await cb(el);
        console.log('async', res, new Date)
    }
}

/*
#foreach does not wait, but async and reduce are spaced by one second
foreach 4 2019-10-14T13:43:47.059Z
foreach 5 2019-10-14T13:43:47.071Z
foreach 6 2019-10-14T13:43:47.071Z
async 1 2019-10-14T13:43:47.071Z
async 2 2019-10-14T13:43:48.073Z
async 3 2019-10-14T13:43:49.074Z
reduce 7 2019-10-14T13:43:50.076Z
reduce 8 2019-10-14T13:43:51.078Z
reduce 9 2019-10-14T13:43:52.080Z
*/ 
async function main(){

    await [4,5,6].forEach(async el=>{
        let res = await slow(el);
        console.log('foreach', res, new Date)
    })
    await asyncForEach([1,2,3], slow);

    await [7,8,9].reduce((acc, el)=>acc.then(async _=>{
        let res = await slow(el);
        console.log('reduce', res, new Date);
        return;
    }), Promise.resolve())
}
main();

Как видно из отметок времени, forEach не ожидает, однако, slow до конца,asyncForEach в своей итерации делает ожидание

Вам может потребоваться либо

  • написать цикл for, как это сделано с asyncForEach
  • использовать стандартные обещания (складывая их):
    [1,2,3].reduce((acc, el)=>acc.then(_=>{
        return slow(el);
    }), Promise.resolve())
    
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...