2016-04-07 bouzuya/b-o-a 0.8.0 をつくった
bouzuya/b-o-a 0.8.0 をつくった。
b-o-a 0.8.0 は handler の方針を変更し、handler chain を非推奨にした。handler chain は handler の出力を次の handler の入力にすること。handler chain の例は次のとおりだ。
import { run, A, O } from 'b-o-a';
import { init as init1 } from 'handler1';
import { init as init2 } from 'handler2';
const main = (): void => {
run((action$: O<A<any>>, options: any): O<A<any>> => {
// handler chain
const a1$ = init1().handler(action$, options);
const a2$ = init2().handler(a1$, options); // a1$ を渡す
return app(a2$, options); // a2$ を渡す
});
};
0.7.x までの handler は handler chain を前提とし、各 handler は自身の関心のある action を処理するほかに、それ以外の action を次に流すようにしていた。こうしないと、handler chain によって、そこで関心外の action をすべて filter してしまうからだ。
0.8.0 からの handler は handler chain を前提とせず、各 handler は自身の関心のある action を処理するが、それ以外の action を次に流さなくなった。必要なら次のようにすれば従来と同じ挙動になる。
const a$ = O.merge(
action$.filter(...),
init().handler(action$, options)
);
そもそも、なぜ handler chain が問題になるのか。
handler chain を想定するとすべての action$ が run(handler, options)
の handler
を通らなくなり、循環しない点が問題だ。handler の chain をたどる過程で知らぬうちに action
が間引かれて、循環しないのは危険だ。たとえば、すべての action を logging することが難しくなるし、それは replay などの実装を困難にする。
新しい handler の方針は単純だ。すべての handler は自身の関心のある action だけを処理すべきで、それ以外は無視すべきだ。すべての handler に無視されれば循環しなくなるので、無限に循環する心配はない。すべての action に共通の処理をはさみたければ、そこだけを chain にし、ほかをすべて O.merge(handler(), handler(), ...)
のようにすべきだ。
なぜ、いままで気づかなかったのかはよく分からない。