繼續往下做整個 Store 之前,我們先來想一下整個 Store 的架構跟資料流
當元件 (component) 或是 Store 自己內部分派一個 (dispatch) Action
時, Dispatcher
接住這個 Action
,交給 Reducer
(或者交給 Effect) ,Reducer
使用前一個 State
處理這個 Action
,產生新的 State
,然後 push 給訂閱者 (Subscriber)
來看程式
interface Action {
type: string;
payload?: any
}
class Dispatcher extends Rx.Subject<Action> {
dispatch(act) {
console.log('got dispatch action ', act.type);
this.next(act);
}
}
class Store extends Rx.BehaviorSubject<Action>{
constructor(private dispatcher, initialState) {
super(initialState);
this.dispatcher
.do((v) => { console.log('do some effect for', v.type)})
.do((v) => { console.log('doing reducer here, got new state after ', v)})
.subscribe(state => {
super.next('new state after ' + state); // new state, push to subscriber
});
}
dispatch(act) { // delegate to dispatcher
this.dispatcher.dispatch(act);
}
// override next to allow store subscribe action$
next(act) {
this.dispatcher.dispatch(act);
}
}
// instanciate new store
const dispatcher = new Dispatcher();
const store = new Store(dispatcher, 'initial State');
// add subscriber
const sub1 = store.subscribe(v => console.log('sub1 ===> ', v));
// start dispatch action
store.dispatch({type: 'Action1'}); // dispatch new action to store
store.dispatch({type: 'Action2'}); // dispatch another action
dispatcher
。dispatcher
跟 initial state
用參數傳入 Store 的 constructor
中,因為 Store 是 BehaviorSubject
一定要在 constructor
中傳入 。dispatch
method 攤派 (delegate) 給 dispatcher
,以後傳入的 Action 就會進入 dispatcher
的 dispatch
,而dispatch
用 dispatcher
的 next
來導入下一個 Action,因為 dispatcher
是 subject
。constructor
讓 dispatcher
開始加工,這裡先用 .do()
預留給 effect
跟reducer
,後面我們再來詳細說明 reducer
如何作用。reducer
後可以用 subscribe
帶出 reducer
產生新的狀態,留在 Store 的 BehaviorSubject
中,這時外面的 subscriber 就會得到新的狀態。store.dispatch({type: 'Action1'})
。上面程式會產生
這個程式就是整個 Store 的大架構,程式相當精簡因為用了 Subject
跟 BehaviorSubject
,它們提供了我們需要基礎的功能,例如接下一個 Action, dispatcher
中間的加工應用了 Observable 的 Operators。
接下來我們要開始來做 Reducer
了,上面的程式還沒使用到狀態,接下來的 Reducer
將會就目前的狀態跟新的 Action 結合產生出新的狀態。