DarthJS
@DarthJS

Как дождаться всех данных при данной конструкции React Redux Async Recursion?

Есть файл с actions в котором есть ассинхронные запросы, но один запрос нужно сделать рекурсией, чтоб не отправлять огромный запрос, а забирать маленькими кусочками. Все вроде ничего, но вот только прорисовка наступает быстрей чем сохраняется последний кусочек в ReduxState

Пример:
myRecursion = (cb) => {  // Рекурсивная функция, которую будем вызывать дальше при выполнении реквеста
 return new Promise(() => {
  Api
   .getSomeData(request)
   .then(response => {
     dispatch(actionHandler(response.item)) // Диспатчим новые айтемы
      if(response.items.length){
         myRecursion(); // Если есть еще данные, вызываемся снова
         return false;
       }
        return true;
   })
   .then(() => cb()) // Вызываем колбек, который является resolve, чтоб зарезолвить промис.
 })
}

// Ниже главные функционал реквестов
const promise = new Promise(resolve => {
const requests = someData.reduce() // тут собирается пачка реквестов

Promise
  .all(requests) // резолвим все реквесты
  .then(response => {
    response.forEach((item, i) => {
     dispatch(actionHandler(item)); // Диспатчим, всё ок
       if(item.type определенного типа мы его загоняем в рекурсию){ // необходимое условие для определенного реквеста
         myRecursion(resolve) // Та самая рекурсия. Я решил запихнуть туда resolve, чтоб его вызвать колбеком по завершению всех следующих реквестов
        }
    })
   });
});
promise.then(() => {
 // По идее все реквесты закончились, но последний резвест не успевает сохраниться в Redux State, и отрисовка некоторых данных получается некорректная, все предыдущие запросы рисуются отлично
})


У кого есть какие идеи, что я не так сделал?
  • Вопрос задан
  • 783 просмотра
Решения вопроса 1
rockon404
@rockon404 Куратор тега React
Frontend Developer
Зачем вам рекурсия? Выглядит как набор костылей. Попробуйте решить задачу по-другому. Например, забрать данные одним запросом, либо реализовать бесконечный скролл с подгрузкой данных по требованию.

Перерисовка наступает тогда когда вы обновляете store. Ничего удивительного.

Если так хотите оставить и использовать свой подход. У вас есть два пути:
1. Добавить в store ключ isAllDataLoaded и обновлять его в редьюсере когда приходит последняя часть данных.
2. Добавить в проект redux-thunk. Переписать свою функцию в async action:
const fetchData = () => async dispatch => {
  const data = [];
  try {
    while(true) {
      const response = await Api.getSomeData({ from: data.length });
      data.push(response.item); // если item это массив, то data.push(...response.item); 
      if(!response.items.length) {
        break;
      }
    }
    
    dispatch(fetchDataSuccess(data));
    
    return data;
  } catch (e) {
    dispatch(fetchDataFail(e));
  }
};


Еще учитесь писать поддерживаемый и читаемых код. Соблюдайте стандарты комьюнити, такие запросы, при использовании redux, принято выносить в async action или сагу.

В API принято реализовывать эндпоинты для получения как одного экземпляра данных, так и целой коллекции.
Возможно, вам стоит написать эндпоинт для получении всей коллекции данных. Потому что сейчас ваш код выглядит как набор костылей, написанных, в попытке заполнить именно эту брешь в API.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы