web-dev-qa-db-fra.com

redux-saga quand utiliser fork?

quelle serait la différence entre les deux approches ci-dessous?

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)
  ]
}

Quand dois-je utiliser une fourchette et quand non?

28
Guilherme Miranda

En général, fork est utile lorsqu'une saga doit démarrer une tâche non bloquante. Le non-blocage signifie ici: l'appelant démarre la tâche et continue son exécution sans attendre qu'elle se termine.

Il existe une variété de situations où cela peut être utile, mais les 2 principales sont:

  • regroupement des sagas par domaine logique
  • conserver une référence à une tâche afin de pouvoir l'annuler/la rejoindre

Votre saga de haut niveau peut être un exemple du premier cas d'utilisation. Vous aurez probablement quelque chose comme:

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

authSaga inclura probablement des choses comme:

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

Vous pouvez voir que cet exemple est équivalent à ce que vous avez suggéré, en appelant avec fork une saga donnant un appel takeEvery. Mais en pratique, vous n'avez besoin de le faire qu'à des fins d'organisation du code. takeEvery est en soi une tâche fourchue, donc dans la plupart des cas, ce serait inutilement redondant.

Un exemple du deuxième cas d'utilisation serait quelque chose comme:

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

Vous pouvez voir dans cet exemple que le monitorUserProfileUpdates s'exécutera pendant que la saga de l'appelant reprendra et attendra le USER_SIGNED_OUT action à envoyer. Il peut en outre en conserver une référence afin de l'annuler en cas de besoin.

Par souci d'exhaustivité, il existe une autre façon de démarrer des appels non bloquants: spawn. fork et spawn diffèrent dans la façon dont les erreurs et les annulations se propagent de l'enfant à la saga parent.

59
VonD