Сага всегда отменяется - PullRequest
0 голосов
/ 09 ноября 2018

Я использую redux-saga и имею следующий код:

function* loginFlow(username, password) {
  try {
    yield call(loginApi, username, password);
    yield put({ type: LOGIN_SUCCESS });
    yield put({ type: TOGGLE_LOGGED_DONE, payload: true });
    yield put(push('/dashboard'));
  } catch (error) {
    yield put({ type: LOGIN_ERROR, error });
  } finally {
    if (yield cancelled()) {
      console.log('ALWAYS CANCELLED');
      // yield put(replace('/login'));
    }
  }
}

// Watcher saga.
function* loginWatcher() {
  while (true) {
    const { username, password } = yield take(LOGIN_REQUESTING);
    const task = yield fork(loginFlow, username, password);
    const action = yield take([LOGOUT, LOGIN_ERROR]);
    if (action.type === LOGOUT) yield cancel(task);
    yield call(logoutUser);
  }
}

Проблема в том, что функция loginFlow всегда отменяется (я вижу 'ALWAYS CANCELLED' в консоли). Даже если я удалю const action = yield take([LOGOUT, LOGIN_ERROR]); и yield call(logoutUser); из loginWatcher.

Я не вижу, чтобы либо LOGOUT, либо LOGIN_ERROR были уволены: Redux devtools output

Есть идеи, что не так с моим кодом?

Обратите внимание, что я использую withRouter в index.js для страницы входа, где выше сага (иначе я получаю пустой экран при перенаправлении):

const withSaga = injectSaga({ key: 'login', saga }); 

export default compose( withReducer, withSaga, withConnect, )(LoginPage); 

С наилучшими пожеланиями

EDIT: Если обернуть loginWatcher в try/catch, я также перейду к finally там:

function* loginWatcher() {
  while (true) {
    try {
      const { username, password } = yield take(LOGIN_REQUESTING);
      const task = yield fork(loginFlow, username, password);
      const action = yield take([LOGOUT, LOGIN_ERROR]);
      if (action.type === LOGOUT) yield cancel(task);
      yield call(logoutUser);
    } catch (error) {
      yield put({ type: LOGIN_ERROR, error });
    } finally {
      if (yield cancelled()) {
        console.log('HERE AS WELL');
        // yield put(push('/login'));
      }
    }
  }
}

1 Ответ

0 голосов
/ 09 ноября 2018

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

В redux-saga саги, запущенные через call() и fork(), рекурсивно отменяются. Сага означает рекурсивно отменяемое задание. Поэтому, когда сага отменяется, вы должны проверить ее родительскую сагу и т. Д.

Этот фрагмент кода вы отправили:

const withSaga = injectSaga({ key: 'login', saga });
export default compose( withReducer, withSaga, withConnect, )(LoginPage)

Google предполагает, что он использует этот пример «редукс-сага + реактивная модель» . Это касается отмены и как ее отключить. Проверьте ссылку, чтобы узнать об этом.

Я не знаком с реактивным шаблоном (экосистема React огромна), но я думаю, что мой ответ, по крайней мере, сужает поиск. Если вы запутались, подумайте о том, чтобы задать отдельный вопрос с помощью .

...