iT邦幫忙

2021 iThome 鐵人賽

DAY 10
1
Software Development

From State Machine to XState系列 第 10

Day10 - 實作一個狀態機 - 3

我們昨天透過一個 object 描述一個狀態機的定義,還記得前天我們的 switch / case 做出的 transition function 嗎?transition function 是一個 純函式(pure function),我們還缺少一個東西來儲存當前的狀態。

State Machine 不完全,沒有一個變數能幫我記憶當下的狀態是什麼,我在使用 transition 時還要另外用一堆變數來儲存 state ,感覺不好維護、也不好維持程式碼的連貫性

試著思考看看 有個 function 叫做 createMachine ,當我們把 狀態機的定義 machineDef 丟進去,他就可以回傳給我們一個能儲存狀態的狀態機

someMachine = createMachine(someMachineDef)

那我們這個 someMachine 會需要有哪些東西?

https://ithelp.ithome.com.tw/upload/images/20210920/20130721SCO6gzH9tL.png
by The Finite State of Reactive Animations

[x] Initial State,
[x] States,
[x] Events,
[_] Transition,
[_] Final States (可能沒有)

上面 [x] 這些東西已經在昨天被我們寫進 machineDef ,那我們應該還缺的是 transition function 跟能儲存當下狀態的 Current State

為了儲存狀態 Current State,程式開發中,目前所知具有狀態性,能儲存狀態的值也是「物件」,所以我們決定採用物件,這個物件會依照 machineDef 當作 configuration。

假設我們希望 someMachine.state 可以拿到當前狀態, someMachine.transition('事件') 可以轉移狀態,所以我們的透過 function 回傳一個物件,實作可以長這樣

function createMachine(machineDef) {
  return {
    // 初始值是 initialState 我們透過這個 object 儲存 state
    state:machineDef.initialState,  
    // 實作  transition
    transition(event){
       ...
    }
  }
} 

那新版的 transition 該怎麼實作,先來看看我們手上有什麼材料,一起來看看昨天的 machineDef

const machineDef = {
  initialState: "站姿、靜止",
  states: {
    "站姿、靜止": {
     on: {
        跳躍: "跳躍中",
        .....

我們可以從 machineDef.states[state] 拿到當前狀態下所有事件對應該的轉換,下個也就是我們昨天說的那個名為 on 的 transition mapping

所以繼續往下走,接著可以透過 machineDef.states[state].on[event],取得發生某個的事件後要轉成的狀態。

所以我們的 transition 應該可以這樣實作,拿到物件的 Current State ,以及使用者要執行的事件 Event

   transition(event){
       const nextState = machineDef.states[this.state]?.on[event]
       this.state = nextState
       return this.state
    }

然後可能查找失敗,當我們拿不到值,transition 不能正確轉換、或說不應該轉換,此時,我們應該就要維持原本的狀態

因為 nextState = transition(previousState, event)的 previusState, event,只要其中一個是不符的話,代表我們不能改變狀態。

   transition(event){
       const nextState = machineDef.states[this.state]?.on[event]
       if(nextState){
         this.state = nextState
       }
       return this.state
    }

如此我們就完成了一個簡單的 state machine

function createMachine(machineDef) {
  return {
    // 初始值是 initialState 我們透過這個object 儲存 state
    state:machineDef.initialState,  
    // 實作  transition
    transition(event){
       const nextState = machineDef.states[this.state]?.on[event]
       if(nextState){
         this.state = nextState
       }
       return this.state
    }
  }
}

https://ithelp.ithome.com.tw/upload/images/20210925/20130721Jz1TOcymQG.png


上一篇
Day09 - 實作一個狀態機 - 2
下一篇
Day11 - 狀態機與現實世界的落差 - 1: Action? Side Effect
系列文
From State Machine to XState31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

2 則留言

0
pjchender
iT邦新手 3 級 ‧ 2021-09-27 21:49:24

狀態機完成了!!

0
TD
iT邦新手 4 級 ‧ 2021-09-28 09:26:43

看到會動了!

我要留言

立即登入留言