Saga Redux: ¿cómo cancelar una tarea de otra que no la inició?

Aug 21 2020

Estoy leyendo este artículo sobre cómo cancelar tareas en Redux saga. Básicamente, el ejemplo que tienen es el siguiente:

function* main() {
  yield call(task1);
  yield cancel(task1);
}

function* task1() {
  <...>
}

Aquí se mainpuede cancelar task1porque lo llamó. En mi código, estoy ejecutando funciones como esta:

function* task1() {
  <...>
}

function* task2() {
  yield cancel(task1);
}

function* main() {
  takeLatest(actionCreator1, task1);
  takeLatest(actionCreator2, task2);
}

Cancelación task1en task2no funciona, probablemente porque task2no invocó task1. ¿Alguien sabe cómo puedo abordar esto?

Respuestas

1 NicholasTower Aug 21 2020 at 06:20

La solución probablemente sea tener su propia implementación de algo similar a takeLatest, pero con lógica adicional para cancelar la otra tarea.

Si solo desea que action2 realice la cancelación adicional, entonces se verá así:

function* main() {
  let firstTask;
  let secondTask;
  while (true) {
    const action = yield take([actionCreator1, actionCreator2]);
    if (firstTask) {
      // Always cancel task 1, whether we got action 1 or action 2
      yield cancel(firstTask);
    }
    if (action.type === "the type of action 1") {
      firstTask = yield fork(task1, action);
    } else {
      if (secondTask) {
        // Only cancel task 2 if we got action 2
        yield cancel(secondTask);
      }
      secondTask = yield fork(task2, action);
    }
  }
}

Si desea que ambas acciones cancelen ambas tareas, es un poco más simple:

function* main() {
  let task;
  while (true) {
    const action = yield take([actionCreator1, actionCreator2]);
    if (task) {
      yield cancel(task);
    }
    if (action.type === "the type of action 1") {
      task = yield fork(task1, action);
    } else {
      task = yield fork(task2, action);
    }
  }
}