generated at
middleware パターンに対する考察
middlewareとは、ここではexpress等の、requestを受けてresponseを返すような構造の構成要素として使われるものを指す


これは、全体としては入力を受けて、出力を返すだけの関数である。
これを、層状にスライスして、どんどん層をフォールバックさせるような構造にしたものがmiddlewareである

js
function donothingMiddleware(req,res,next) { return next(req) }


さて、ここでreducerによるstate patternを考えて、これをmiddleware化する

ts
type Reducer = (state: State, action: Action) => State

入力が前ステートとアクション
出力が新しいステート

middlewareはこのように書ける。
ts
function middlewareExample(state:State, action:Action, next:(state:State,action:Action)=>State) { console.log('before') const nextState = next(state,action) console.log('after') return nextState }

さて、ここで、入出力の型をちょっと工夫してみよう
まず、nextはReducer型であることに注意したい。
その上で、nextのみを先に引数として受け取る形でカリー化する
ts
const middlewareExample = (next: Reducer) => (state:State, action:Action) => { console.log('before') const nextState = next(state,action) console.log('after') return nextState }
そうすると、nextを受け取り引数をひとつ受け取った後に返す型が、これもまたReducerであることが分かる

ts
const middlewareExample: (next:Reducer) => Reducer = (next) => (state, action) => { console.log('before') const nextState = next(state,action) console.log('after') return nextState }

これを改めて、Middleware型としよう
ts
type Middleware = (next:Reducer) => Reducer const middlewareExample: Middleware = (next) => (state, action) => { console.log('before') const nextState = next(state,action) console.log('after') return nextState }

さて、この形のmiddlewareを複数結合するにはどうすればいいか?

console.logしたり、型をみながらイジるとわかるが、こんな感じだ
ts
function combine(...middlewares: Middleware[]): Middleware { return (initialReducer) => middlewares.reduceRight( (next, middleware) => middleware(next), initialReducer ); }
複数のmiddlewareを繋げたら、ひとつのmiddlewareになることを言っている



ts
const passthrough = (s: string): Middleware => (next) => (state, action) => { console.log("start", s); const nextState = next(state, action); console.log("end", s); return nextState; }; const m = combine( passthrough("1"), passthrough("2"), passthrough("3"), passthrough("4") ); m((state) => { console.log("端っこです"); return state; })(initialState, action);

log
start 1 start 2 start 3 start 4 端っこです end 4 end 3 end 2 end 1

こういう感じになる



middlewareの配列自体もreduceしてるから、頭がこんがらがるかも


いざ作ってみたが、次のstateを求めるためのreducerをmiddleware的に、後続処理を扱えるようにするメリットを、現状まだ遭遇できてない

後続処理がなにか選択範囲を求めるようなもので、それに対する操作をしたいときとか? 
そういうときも、選択と操作は別のアクションで各々実行されるからなあ

早期returnは必要であるのは分かる

なにか後続の処理が大きいステートを指していて、そのステートが抜けて親に任せるケースとかには使えるかも