Библиотека асинхронных запросов для react?

Если ajax запрос данных с сервера может быть длительным (2 и более секунд), в современных фреймворках типа react без проблем можно отображать progressbar, значок загрузки и т.п. Но в это время пользователь имеет право работать с приложением дальше, нажимать различные кнопки, т.е. запускать другие процессы загрузки данных и т.п. Так вот вопрос - существует ли на данный момент библиотека, которая способна разрулить такой хаос в действиях пользователя?
Пример некорректных возможных обработок:
1) Клиент выбрал фильтры в форме поиска, нажал кнопку, данные грузятся... далее юзер выбрал другие параметры фильтров, снова нажал кнопку - в результате второй запрос теоретически может отработать быстрее первого, затем придут данные от первого запроса, в результате - параметры заданных юзером фильтров будут от второго запроса, а отображаемый результат - от первого.
2) Повторная отсылка данных формы - тут конечно есть стандартный метод блокирования кнопки от нажатия, но желательно бы это перенести на функциональность быблиотеки.

Вот примерное тз для такой библиотеки:
Типы процессов:
1) Получение доп данных (например полный текст статьи в блоге)
- Если target компонент скрывается (переходим на другую вкладку, закрыли компонент, и т.п.) - то отменяем процесс.
- Если повторный запрос тех же самых данных - игнорируем такой запрос.
- Отменить загрузку можем и по нажатию кнопки.
2) Получение дынных формы с заданными фильтрами на входе (поиск по параметрам например)
- Во время загрузки фильтры показываем как их выбрал юзер.
- Если target компонент скрывается, то отменяем процесс.
- Если задали другие фильтры на входе, то отменяем прежний процесс и создаем новый.
- Если отменили загрузку, то возвращаем фильтры в исходное состояние.

+ данные могут поступать по websocket

В общем случае это получается некий конечный автомат с правилами на любой штатный/внештатный случай. Есть ли сейчас что-то такое готовое?
  • Вопрос задан
  • 1351 просмотр
Пригласить эксперта
Ответы на вопрос 4
Да, такая библиотека есть. Проблема в том, что в JS нативные промисы (Promise) нельзя отменить (not cancelable)... но при этом - у нас есть генераторы, которые вполне себе позволяют имитировать отмену выполнения какой-либо функции, скажем, в середине.

Для того, чтобы все заработало - вам нужно использовать связку из любой понравившейся библиотеки для непосредственно запросов (я предпочитаю isomorphic-fetch), затем взять redux и middleware для него (редакса) - redux-saga.

Если вы не знакомы с экосистемой редакса или первый раз слышите про redux-saga - прочтите документацию, посмотрите уроки. Если вкратце - библиотека построена на генераторах. Функция-генератор возвращает итератор и ее выполнение прекращается каждый раз, когда мы возвращаем итератору новое значение (yield)

Ниже продемонстрирую как это примерно работает:

function* myCancelableAction(someData) {
  // вернет итератору промис и приостановит работу функции до следующего вызова next
  // в нашем случае - функция продолжит выполнение, когда придет ответ сервера
  const response = yield doAjaxRequest(someData) 
  yield dispatchSuccessAction(response)
}

const action = myCancelableAction();
const promise = action.next().value // fetch promise

promise.then(response => {
  // если новых запросов не поступило
  if(!newRequestIsComing) {
    // мы можем передать значение в нашу функцию (через next)
    console.log(action.next(response).value); // dispatched action
  }
})


Таким образом, после того, как функция вернула значение первый раз, применительно к теме поста это будет "сделай AJAX-запрос", мы можем не выполнять ее дальше (если захотим). Отменить ajax запрос в этом случае не получится, но мы можем просто не учитывать его результаты (не диспатчить success-экшен, например).

UPD1 обновил пример кода
Ответ написан
Комментировать
dpigo
@dpigo
Front-end developer
Посмотрите в сторону RxJS
Ответ написан
@LiguidCool
Ну так это издержки асинхронности, за которые так любят, и так ненавидят JS.
Думаю для того же React или Angular это все изрежки программиста, писавшего код. По большому счету нельзя блокировать что-то на время выполнения асинхрона. Например вы сделали запрос данных и на это время через state (я про React) заблокировали кнопку ... А потом ваш AJAX взял и не вернулся (ну магия какая-то). И абзац - жми F5.
И кстати, может если сервер так долго отдаёт данные, то ... Хм пусть отдает все сразу, а фильтрует пусть фронтэнд. Попробуйте, может это ваше решение.
Ответ написан
maxfarseer
@maxfarseer
https://maxpfrontend.ru, обучаю реакту и компании
Тоже столкнулся с подобной проблемой, опишу как это в черновике выглядит у себя, но в целом пока красиво решено не было:

Есть проект, на бэкэнде elixir+phoenix. Мне в каждом сообщении приходит ref + автоинкреметный id. Следовательно, когда я делаю первый запрос и данные идут долго, а потом второй запрос и данные приходят быстрее, то ref будет больше и я просто в редьюсере игнорирую старый ответ (в стиле, action.ref < state.ref => верни текущий стэйт).

P.S. если используете сокеты, как вы "замедляете" получение ответа? Мне пришлось попросить "бэкэнд" отвечать медленнее, для тестирования этой проблемы. Так как в chrome devtools в нетворке "замедление" не работало для запросов по сокету.
Ответ написан
Комментировать
Ваш ответ на вопрос

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

Войти через центр авторизации
Похожие вопросы
summer Ярославль
от 100 000 до 140 000 ₽
КРАФТТЕК Санкт-Петербург
от 60 000 до 80 000 ₽
19 апр. 2024, в 22:48
100 руб./за проект
19 апр. 2024, в 20:43
20000 руб./за проект