到目前為止,我們伸縮自如的圈圈叉叉遊戲已經很像樣了,但是目前判斷勝負的工作還是需要玩家自己來判斷。我們希望電腦可以幫助我們判斷勝負,這樣就不用自己在那邊算自己是不是已經連成一條線,因為人工判讀總是容易出錯,邊玩還要邊注意自己是不是不小心贏了,真的很掃興。所以接下來我們希望他可以按照我們所設定的 winnerCondition 來判斷獲勝者。
在這之前我們先來想一下判斷勝負的時機,我希望在下完每一步棋之後判斷一次勝負,所以有可能的做法是在 reducer裡面下完棋之後隨後判斷勝負,然後把值存起來。或者透過 Day05 提到的 reselect 來做,因為勝負判斷的結果,也可以說是我設計的參數中, blocks 和 winnerCondition 的衍生資料。
但是因為我們 Day01 有說,我們希望我們有一個 Toggle Switch Button 可以切換電腦是否自動下棋,所以之後判斷勝負的流程可能會變得比較複雜。
可能的狀況有:
我自己覺得如果把所有的狀況考慮進去,然後這些狀況的判斷都寫在 reducer 裡面的話,會變得眼花繚亂,而且很可能因為邏輯太複雜而容易寫錯,不易除錯。
所以這邊我想要借用一下 redux-observable
的 Epics
來幫助我解決我的煩惱。redux-observable 是一個 redux 的 middleware,Netflix 利用它來解決複雜的非同步相關問題。redux-observable 真的不是那麼容易上手,所以我把我讀過的文章覺得有助於理解 redux-observable 的其中幾篇,在這邊分享給大家,然後安裝及設定方式可以參考官方教學,我也提供我的 程式碼 給大家參考,寫錯的地方也麻煩大大們幫忙指正,謝謝。
redux-observable
Epics
希望是最淺顯易懂的 RxJS 教學
30 天精通 RxJS
Epics run alongside the normal Redux dispatch channel, after the reducers have already received them--so you cannot "swallow" an incoming action. Actions always run through your reducers before your Epics even receive them.
根據官網的說明,Epics 是一個 Actions in, actions out
的函數,我們發送完 action,在 reducers 接收到 action 之後,Epics 函數才會監聽並接收到 action。簡單來說, action 會在我們發送完之後,依序經過 reducer 以及 Epics 函數,而且因為 Ecpis 是 action out,所以在 Ecpis 做完事情之後,可以再發送 action 回到 reducer,不過這邊要小心不要產生無窮迴圈。
有了這個 Epic 函數之後,剛剛提到的複雜的工作,好像可以變得簡單。
我們按下一個 block 之後,會發送一個 type 為 SET_BLOCK_VALUE
的 action 到 reducer 來更新我們的 blocks 參數,接下來,我們寫一個 Epic 函數來監聽 type 為 SET_BLOCK_VALUE 的 action,所以在 reducer 更新完 blocks 之後,我們可以在 Epic 函數裡面判斷勝負,判斷完之後,再發送一個 type 為 SET_WINNER 的 action 回到 reducer,把勝負的結果存回 state。
電腦自動下棋也可以這麼做,用上面同樣的方法,判斷接下來這一棋是否電腦自動下棋,可以在每次的判斷勝負之後進行,所以判斷完勝負並在 reducer 儲存結果之後,我們可以用 Epic 函數來監聽 type 為 SET_WINNER 的 action,並在這邊決定是否透過電腦下棋。
所以可以很簡單的分成兩種狀況:
成功安裝好之後,可以看到下面這個效果,action 會依序經過 reducer ,再經過 Epic 函數。
準備好之後,明天我們就要開始實做勝負判斷了!