Шаблон ожидания/успеха/неудачи Redux Saga – как справиться с прерыванием

Я использую redux-saga и @reduxjs/toolkit. Я делаю несколько запросов к веб-сервису и сохраняю их ответы в redux, и следую шаблону «ожидание/успех/неудача», который упоминался в нескольких местах. Для моей саги о редуксе:

export default function* rootSaga() {
    yield takeEvery(actionGetData.toString(), handleGetData);
}

с моей функцией генератора:

function* handleGetData(action: any): Generator<any, any, any> {
    yield put({ type: 'ACTION.GETDATA_PENDING', payload: action.payload });
    try {
        const response = yield call(apiRequest);
        const responseData = response.data;
        yield put({ type: 'ACTION.GETDATA_FULFILLED', payload: { name: action.payload, data: responseData } });
    } catch (error: any) {
        yield put({ type: 'ACTION.GETDATA_FAILED', payload: { name: action.payload, data: error.message } });
    }
}

Я сохраняю этот статус (ожидание, успех, сбой) в redux, и на экране появляется визуальный компонент, соответствующий этому статусу — анимация загрузки, уведомление об успехе/неуспехе и т. д.

Все это прекрасно работает, но проблема в том, что когда это apiRequest занимает некоторое время и пользователь преждевременно отменяет запрос, скажем, закрыв страницу до того, как запрос веб-сервиса вернет ответ. В этом случае, когда пользователь перезагружает страницу, статус зависает в состоянии «загрузка», за исключением того, что на этот раз apiRequest не будет установлено, поэтому нет возможности выйти из этого состояния с успехом или неудачей, поэтому никогда Пользователю отображается анимация окончания загрузки, и нет ничего, что могло бы повторить запрос веб-сервиса.

Как я могу это решить? Есть ли способ вызвать функцию очистки, которая может быть выполнена до завершения функции (например, немедленно вызвать действие «сбой», если страница преждевременно остановлена)? Есть ли способ «просмотреть» этот «ожидающий» статус и вызвать повторную попытку, если он завис на определенное время?

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

C. Helling 09.07.2024 18:27

Я вижу, что Тайлер отредактировал/удалил субъективно значимые части вашего сообщения, но оно все еще слишком широкое/открытое. Вы уже пробовали что-нибудь конкретное? Я решил аналогичную проблему в предыдущем проекте, отслеживая все активные сетевые запросы с помощью очереди. Когда запросы удовлетворяются, они удаляются из очереди. Магазин Redux был сохранен в долгосрочном хранилище, например. localStorage, и когда приложение запускается/монтируется, одно из первых действий, которое оно делает, — это выполнение очереди. Это всего лишь один из способов решения проблемы. Скорее всего, в вашем распоряжении есть несколько решений.

Drew Reese 09.07.2024 23:05

@DrewReese Итак, где вы размещаете вызов для выполнения очереди? Я уже отслеживаю сетевые запросы, но моя проблема заключается в том, как определить, когда запросы ожидаются слишком долго, и, например, выждите их и подведите их.

C. Helling 10.07.2024 00:19

Я реализовал обработку очереди при монтировании приложения и периодически с интервалом примерно в 15 минут. Я использовал Redux-Toolkit-Query (с тайм-аутами и повторными попытками), если вызов конечной точки был успешным, то все хорошо, но если время ожидания истекло/ошибка/и т. д., я бы добавил данные запроса, конечную точку и т. д. в очередь, которая будет периодически обрабатывается. Ожидающие запросы удаляются из очереди и выполняются повторно, а в случае неудачи они снова добавляются в очередь.

Drew Reese 10.07.2024 00:54

«но моя проблема в том, как определить, когда запросы находятся в ожидании слишком долго, и, например, определить время их ожидания и не выполнить их». - Это зависит от библиотеки/реализации, которую вы используете для выполнения своих запросов.

Drew Reese 10.07.2024 00:55
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
1
5
67
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

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

function* handlePendingRequestsSaga() {
    yield put({ type: actionClearPendingDataRequests.toString() });
    yield put({ type: actionRetryRejectedDataRequests.toString() });
}

export default function* rootSaga() {
    yield handlePendingRequestsSaga();
    yield takeEvery(actionGetData.toString(), handleGetResource);
}

И в соответствующих редукторах тот, что для actionClearPendingDataRequests, принимает запросы, которые были помечены как ожидающие, и перемещает их в число отклоненных, а тот, что для actionRetryRejectedDataRequests, будет повторять запросы, которые ранее были помечены как отклоненные. Поскольку handlePendingRequestsSaga срабатывает при инициализации (скажем, когда страница обновляется или впервые загружается), любые прерванные запросы будут помечены как отклоненные и автоматически повторены, а любые запросы, которые ранее не удались, также будут повторены (один раз). Если они снова терпят неудачу без перерыва, рабочий процесс страницы выполняется так, как предполагалось (показывает пользователю сообщение об ошибке для неудавшихся запросов и т. д.).

Другие вопросы по теме