redux-saga, когда использовать форк?

в чем будет разница между двумя приведенными ниже подходами?

export function* watchLoginUser() {
  yield takeEvery(USER_LOGIN, loginUser)
}
export function* watchLogoutUser() {
  yield takeEvery(USER_LOGOUT, logoutUser)
}
export function* watchGetParties() {
  yield takeEvery(PARTIES_GET, getParties)
}
export default function* root() {
  yield [
    fork(watchLoginUser),
    fork(watchLogoutUser),
    fork(watchGetParties)
  ]
}
export default function* root() {
  yield [
    takeEvery(USER_LOGIN, loginUser),
    takeEvery(USER_LOGOUT, logoutUser),
    takeEvery(PARTIES_GET, getParties)
  ]
}

Когда мне нужно использовать вилку, а когда нет?


person Guilherme Miranda    schedule 21.03.2017    source источник


Ответы (2)


В общем, fork полезно, когда в саге нужно запустить неблокирующую задачу. Неблокирование здесь означает: вызывающий объект запускает задачу и продолжает выполнение, не дожидаясь ее завершения.

Это может быть полезно во множестве ситуаций, но есть 2 основные из них:

  • группировка саг по логическому домену
  • сохранение ссылки на задачу, чтобы иметь возможность отменить / присоединиться к ней

Ваша сага верхнего уровня может быть примером первого варианта использования. Скорее всего, у вас будет что-то вроде:

yield fork(authSaga);
yield fork(myDomainSpecificSaga);
// you could use here something like yield [];
// but it wouldn't make any difference here

Где authSaga, вероятно, будет включать такие вещи, как:

yield takeEvery(USER_REQUESTED_LOGIN, authenticateUser);
yield takeEvery(USER_REQUESTED_LOGOUT, logoutUser);

Вы можете видеть, что этот пример эквивалентен тому, что вы предложили, вызывая с fork сагу, дающую takeEvery вызов. Но на практике это нужно делать только для целей организации кода. takeEvery - это разветвленная задача, поэтому в большинстве случаев это будет бесполезно избыточным.

Пример второго варианта использования будет примерно таким:

yield take(USER_WAS_AUTHENTICATED);
const task = yield fork(monitorUserProfileUpdates);
yield take(USER_SIGNED_OUT);
yield cancel(task);

В этом примере вы можете видеть, что monitorUserProfileUpdates будет выполняться, пока продолжается сага о вызывающем абоненте, и ожидает отправки действия USER_SIGNED_OUT. Кроме того, он может хранить ссылку на него, чтобы при необходимости отменить его.

Для полноты картины есть еще один способ начать неблокирующие вызовы: spawn. fork и spawn отличаются тем, как ошибки и отмены перемещаются от дочерней к родительской саге.

person VonD    schedule 22.03.2017

Обычно fork становится более полезным в некоторых случаях, когда есть несколько отправок вызовов API, причина в том, что вы можете отклонить эти выборки, создав экземпляр отмены из задачи, например. cancel(task1);

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

Есть 2 способа отменить задачу.

база из документации redux-saga Отмена неблокирующего эффекта

import { take, put, call, fork, cancel } from 'redux-saga/effects'

// ...

function* loginFlow() {
  while (true) {
    const {user, password} = yield take('LOGIN_REQUEST')
    // Non-Blocking Effect which is the fork
    const task = yield fork(authorize, user, password)
    const action = yield take(['LOGOUT', 'LOGIN_ERROR'])
    if (action.type === 'LOGOUT'){
      //cancel the task
      yield cancel(task)
      yield call(Api.clearItem, 'token')
    }
  }
}

OR


import {call, put, fork, delay} from 'redux-saga/effects';
import someAction from 'action/someAction';

function* fetchAll() {
  yield fork(fetcher, 'users');
  yield fork(fetcher, 'posts');
  yield fork(fetcher, 'comments');
  yield delay(1500);
}

function* fetcher(endpoint) {
  const res = yield call(fetchAPI, endpoint);
  if (!res.status) {
    throw new Error(`Error: ${res.error}`);
  }
  yield put(someAction({payload: res.payload}));
}

function* worker() {
  try {
    yield call(fetchAll);
  } catch (err) {
    // handle fetchAll errors
  }
}

function* watcher() {
  yield takeEvery(BLOGS.PUSH, worker);
}

Добро пожаловать :)

person Maker    schedule 07.07.2021