redux-sagaのall([fork])パターンは、即座にfinallyに突入してしまう

function* subtask() {
  try {
    yield all([
      takeEvery(action, hoge),
      fork(poyo)
    ])
  } finally {
    if (yield cancelled()) {
      // 後処理
    }
  }
}

subtaskがcancelされたときに後処理が実行されてほしい。ところが、この書き方だとただちにfinallyブロックが評価されます。cancelledはfalseを返すので、後処理はうまく行われません。

yield all([
  takeEvery(action, hoge),
  fork(poyo),
  take(dummyAction),
])

みたいなことをするとfinallyに突き抜けることはありませんでした。

なお、ちゃんとドキュメントに書かれていました。

redux-saga.js.org

There is another popular pattern when designing root saga: nesting fork effects in an all effect. By doing so, you can get an array of task descriptors, and the code after the all effect will be executed immediately because each fork effect is non-blocking and synchronously returning a task descriptor.

Note that though fork effects are nested in an all effect, they are always connected to the parent task through the underlying forkQueue. Uncaught errors from forked tasks bubble to the parent task and thus abort it (and all its child tasks) - they cannot be caught by the parent task.

よかったですね。allの中身が3, 4個くらいならばallを使わずに書くのがわかりやすいかもしれません。

redux-sagaはblocking Effectとnon-blocking Effectの区別が死ぬほど重要です。注意してやっていきましょう。