¿Cuál sería la diferencia entre los dos enfoques a continuación?
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) ] }¿Cuándo necesito usar tenedor y cuándo no?
En general, la fork es útil cuando una saga necesita iniciar una tarea sin bloqueo. No bloquear aquí significa: la persona que llama inicia la tarea y continúa ejecutándose sin esperar a que se complete.
Hay una variedad de situaciones en las que esto puede ser útil, pero las 2 principales son:
Su saga de nivel superior puede ser un ejemplo del primer caso de uso. Es probable que tengas algo como:
yield fork(authSaga); yield fork(myDomainSpecificSaga); // you could use here something like yield []; // but it wouldn't make any difference here Donde authSaga probablemente incluirá cosas como:
yield takeEvery(USER_REQUESTED_LOGIN, authenticateUser); yield takeEvery(USER_REQUESTED_LOGOUT, logoutUser); Puede ver que este ejemplo es equivalente a lo que sugirió, llamando con un fork a una saga que produce una llamada a takeEvery . Pero en la práctica, solo necesita hacer esto para fines de organización del código. takeEvery es en sí mismo una tarea bifurcada, por lo que en la mayoría de los casos, esto sería inútilmente redundante.
Un ejemplo del segundo caso de uso sería algo como:
yield take(USER_WAS_AUTHENTICATED); const task = yield fork(monitorUserProfileUpdates); yield take(USER_SIGNED_OUT); yield cancel(task); Puede ver en este ejemplo que monitorUserProfileUpdates se ejecutará mientras se reanuda la saga de la persona que llama y espera a que se envíe la acción USER_SIGNED_OUT . Además, puede mantener una referencia al mismo para cancelarlo cuando sea necesario.
En aras de la exhaustividad, hay otra forma de iniciar llamadas sin bloqueo: spawn . fork y spawn difieren en la forma en que los errores y las cancelaciones burbujean de la saga secundaria a la principal.
Por lo general, la fork se vuelve más útil para algunos casos que tienen múltiples envíos de llamadas API, la razón es que puede rechazar esas recuperaciones instanciando la cancelación de la tarea, por ejemplo, cancel(task1);
Útil si el usuario final sale de la aplicación a la fuerza o si una de las tareas falló y genera un problema a partir de sus instrucciones, estrategia y lógica y podría ser razonable cancelar o finalizar las tareas de procesamiento actuales en su saga;
Hay 2 formas de cancelar la tarea
base de la documentación de redux-saga Cancelación de efecto sin bloqueo
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') } } }O
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); }Bienvenido :)