Как отменить сагу, когда отправлено определенное действие - PullRequest
0 голосов
/ 20 марта 2019

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

Мне нужно отменить задачи checkAuth и выйти из системы, когда отправлено действие LoginActionType.REQUEST_SEND.

function* handleLoginFetch(userCredentialsAction: PayloadAction<LoginActionType, UserCredentials>) {
    try {
        const response: AxiosResponse<AuthResponse> = yield call($http.put, '/users/login', userCredentialsAction.payload);

        if (response.status === HttpStatusCode.OK) {
            yield put(login.success(response.data.user));
        }
    } catch (error) {
        yield put(login.failure());
    }
}

function* handleCheckAuthFetch() {
    try {
        const response: AxiosResponse<AuthResponse> = yield call($http.get, '/users/logged-user', {
            params: { 'include': 'user_user_permissions' }
        });

        if (response.status === HttpStatusCode.OK) {
            if (yield select(getUserLoggedIn)) {
                yield put(login.success(response.data.user));
            } else {
                yield put(checkLocalAuth.success(response.data.user));
            }
        }
    } catch (error) {
        yield put(checkLocalAuth.failure());
    }
}

function* handleLogoutFetch() {
    try {
        const response: AxiosResponse = yield call($http.put, '/users/logout');

        if (response.status === HttpStatusCode.OK) {
            yield put(logout.success());
        }
    } catch (error) {
        yield put(logout.failure())
    }
}

export default function* userSaga() {
    yield takeLatest(LoginActionType.REQUEST_SEND, handleLoginFetch);
    yield takeLatest(CheckLocalAuthActionType.REQUEST_SEND, handleCheckAuthFetch);
    yield takeEvery(LogoutActionType.REQUEST_SEND, handleLogoutFetch);
}

Ответы [ 2 ]

0 голосов
/ 07 апреля 2019

Ответ NoriSte действительно помог мне понять, как решить мою проблему. Я немного больше изучил документацию по Saga и в итоге нашел это решение.

export default function* userSaga() {
    const checkAuthTask = yield takeLatest(CheckLocalAuthActionType.REQUEST_SEND, handleCheckAuthFetch);
    const logoutTask = yield takeEvery(LogoutActionType.REQUEST_SEND, handleLogoutFetch);

    yield takeLatest(LoginActionType.REQUEST_SEND, function*(userCredentialsAction: PayloadAction<LoginActionType, UserCredentials>) {
        if(checkAuthTask) yield cancel(checkAuthTask);
        if(logoutTask) yield cancel(logoutTask);

        yield fork(handleLoginFetch, userCredentialsAction);
    });
}
0 голосов
/ 26 марта 2019

Вы могли бы:

  • "внедряет" самостоятельно то, что делает takeLatest. Документы говорят

Появляется сага о каждом действии, отправляемом в Магазин, которое соответствует шаблону. И автоматически отменяет все предыдущие саги, запущенные ранее, если они все еще выполняются.

Таким образом, вместо записи yield takeLatest(CheckLocalAuthActionType.REQUEST_SEND, handleCheckAuthFetch); вы можете написать функцию, которая делает то же самое

export default function* forkHandleCheckAuthFetch() {
  let task;

  while (true) {
    // this loop stops here until one of the actions is triggered
    const action = yield take([CheckLocalAuthActionType.REQUEST_SEND, LoginActionType.REQUEST_SEND]);

    // both the actions cancel the previous forked task (similar to what `takeLatest does`)
    if (task) {
      cancel(task);
    }

    // only the "correct" action starts the desided behaviour
    if (action.type === CheckLocalAuthActionType.REQUEST_SEND) {
       // a fork can be cancelled...
      task = yield fork(handleCheckAuthFetch, action);
    }
  }
}

(функция takeLatest spawn - сага, в то время как моя реализация fork - сага, но пока не беспокойтесь об этом)

  • то же самое, что мы можем сделать для handleLogoutFetch
export default function* forkHandleLogoutFetch() {
  let task;
  while (true) {
    const action = yield take([LogoutActionType.REQUEST_SEND, LoginActionType.REQUEST_SEND]);
    if (task) {
      cancel(task);
    }
    if (action.type === CheckLocalAuthActionType.REQUEST_SEND) {
      task = yield fork(handleLogoutFetch, action);
    }
  }
}
  • и затем измените userSaga на
export default function* userSaga() {
  yield forkHandleCheckAuthFetch();
  yield forkHandleLogoutFetch();
  yield takeLatest(LoginActionType.REQUEST_SEND, handleLoginFetch);
}

Итак, теперь:

  • ваше CheckLocalAuthActionType.REQUEST_SEND действие вызывает handleCheckAuthFetch, как это было до моей реализации
  • ваше LogoutActionType.REQUEST_SEND действие вызывает handleLogoutFetch, как это было до моей реализации
  • действие LoginActionType.REQUEST_SEND отменяет каждый запуск handleCheckAuthFetch и handleLogoutFetch sagas

Это то, что я делаю в своих проектах, вы должны абстрагировать их от служебной функции, мне важно, чтобы вы поняли, как она работает и как ее реализовать ?

...