iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 9
0
Modern Web

ngrx/store 4 學習筆記系列 第 9

[ngrx-store-9] 用 Observable 來理解 Dispatcher 跟 Store

用 Observable 來理解 Dispatcher 跟 Store

接下來幾篇並不是要實際做一個 ngrx/store, 而是讓我們用 Observable 的觀念來剖析 ngrx/store 內部的運行方式,實際的 ngrx/store 效率會更好,也會更優化,這裡參考的是這篇Comprehensive Introduction to @ngrx/store,我們希望用模擬的方式來理解它的運作,讓它不再神秘。

先回顧一下 Flux 的兩個核心 Dispatcher 跟 Store
https://ithelp.ithome.com.tw/upload/images/20171225/20103574UKL1wIRck5.png
圖片來源

Dispatcher

我們將 Dispatcher單獨看一下,它的任務是觀察 Action 的資料流,產生 State 的資料流,而這種既是 Observer 又是 Observable 的,我們之前有提過,就是所謂的 Subject
https://ithelp.ithome.com.tw/upload/images/20171225/20103574Jz4SekEBYB.png
模擬程式如下

interface Action {
  type: string;
  payload?: any
}

// dispatcher
class Dispatcher extends Rx.Subject<Action> {
  dispatch(action: Action) {
    this.next(action);
  }
}

const dispatcher = new Dispatcher();

const subscribe1 = dispatcher.subscribe(v => console.log('sub1 ===> ', v));
const subscribe2 = dispatcher.subscribe(v => console.log('sub2 ===> ', v));

dispatcher.dispatch({type: 'Action1'});
dispatcher.dispatch({type: 'Action2'});

codepen
簡單說明一下

  1. Action 基本上是一個物件,用 Typescript 定義的話就是
interface Action {
  type: string;
  payload?: any
}

2.Dispatcher 的 dispatch 其實就是Subjectnext
3.Dispatcher 會在 Store 的內部作業加工後產生新的狀態 State,但這要等到我們加入 Reducer後,我們以後會談到。

Store

Store 基本上也是觀察 Action 資料流,輸出 State 資料流,但 Store 還有一個任務,我們先看下面的例子

interface Action {
  type: string;
  payload?: any
}

// first store with Subject
class FirstStore extends Rx.Subject<Action>{}

const firstStore = new FirstStore();
const sub1 = firstStore.subscribe(v => console.log('sub1 ===> ', v));
const sub2 = firstStore.subscribe(v => console.log('sub2 ===> ', v));

firstStore.next({ type: 'Action1' });
const sub3 = firstStore.subscribe(v => console.log('sub3 ===> ', v));
// sub3 did not get current state

如果我們跟 Dispatcher 一樣使用 Subject 的話,當sub3subscribe時,並不能取到最後的狀態(State),然而 store 會直接面對外面的客戶(subscribers),所以我們要的是
https://ithelp.ithome.com.tw/upload/images/20171225/20103574THuzE6551t.png
還好 RxJS提供了另一種Subject,這種稱為BehaviorSubject是跟Subject一樣可以當 Observer 也可以當 Observable, 除此之外它還會保留最後一筆資料,當有新的 subscriber 時,它可以提供, 例子如下

interface Action {
  type: string;
  payload?: any
}

// use BehaviorSubject
class SecondStore extends Rx.BehaviorSubject<Action> {
  constructor(initialState) {
    super(initialState);
  }
}

const secondStore = new SecondStore('initial State');
const sub4 = secondStore.subscribe(v => console.log('sub4 ===> ', v));
const sub5 = secondStore.subscribe(v => console.log('sub5 ===> ', v));
secondStore.next({ type: 'Action2'});
const sub6 = secondStore.subscribe(v => console.log('sub6 ===> ', v));
// sub6 get state as well

codepen
它的輸出會跟我們預期般,都會有最新的資料,這裡的輸出輸入都還是 Action, 因為要等到將 Store 跟 Dispather 結合之後,我們才會看到之間的轉換,下次我們就來看如何將 Store 跟 Dispatcher 結合,結合後會是整個 ngrx/store 的大架構。


上一篇
[ngrx/store-8] Javascript Mutable 跟 Immutable 資料型態
下一篇
[ngrx/store-10] Store 的大架構
系列文
ngrx/store 4 學習筆記30

1 則留言

0
mattchen0512
iT邦新手 5 級 ‧ 2020-08-18 14:35:06

====補充更新====
CodePen中範例 Rx.subject會出現 undefine錯誤
將Rx開頭變更成 rxjs.subject即可觀看範例

我要留言

立即登入留言