2

I'm trying to find a simple and easy way to cancel all running sagas within a "page" when the user decides to navigate to another "page" within the app... We are not using routing, but instead each "page" is its own widget within a larger host application that is responsible for creating and loading each page when the user navigates...

Currently, we are using redux-saga and have setup logic like so (simplified for brevity) when a page widget is created and loaded...

// page-sagas
export function* rootSaga() {
  const allSagas = [
    // ... all sagas used by page (example) ...
    // function* watchFoo() {
    //   yield takeEvery(FooAction, foo);
    // }
  ];
  yield all(allSagas.map((saga) => call(saga)));
}

// page-widget
onLoad = () => {
  const sagaMiddleware = createSagaMiddleware();
  const store = createStore(reducer, initState, applyMiddlware(sagaMiddleware));
  sagaMiddleware.run(rootSaga);
}

Ideally, I'd prefer to avoid having to add forking logic to every single saga in every single page-widget, and looking at the Redux-Saga Task API, it says you can cancel a task returned by the call to middleware.run, but I'm wondering if this propagates down to all nested / child sagas that are currently in progress, or if there are any issues / gotcha's I should be aware of:

Example:

// page-widget
onLoad = () => {
  ...
  this.task = sagaMiddlware.run(rootSaga);
}

destroy = () => {
  this.task.cancel();
}
Joshua Barker
  • 987
  • 2
  • 11
  • 23
  • 3
    `cancel` will stop all the child sagas from yielding any more effects, but if you have "in-flight" async code (for instance), this won't magically cancel... but because you're not yielding any more effects, this shouldn't affect application state. – spender Sep 12 '19 at 18:26
  • @spender just to clarify, you're saying that this won't cancel something like an in-flight AJAX request, but it will stop the saga from continuing after that request returns? – Joshua Barker Sep 12 '19 at 18:32
  • 2
    Exactly that, yes. – spender Sep 12 '19 at 19:16
  • If you want to cancel in-flight ajax requests there are patterns to do that but as mentioned it doesn't magically happen. It requires saving a reference to whatever mechanism you have to cancel the request before `yield`ing the associated promise and then cancelling in an `if (yield cancelled())` block in the `finally` clause wrapping the request execution. – azundo Sep 12 '19 at 19:33
  • 1
    @azundo yeah, I'm not as concerned about the in-flight request... just the saga... so sounds like this should work... thanks everyone! – Joshua Barker Sep 12 '19 at 20:05

0 Answers0