iT邦幫忙

2021 iThome 鐵人賽

DAY 27
0
Software Development

From State Machine to XState系列 第 27

Day27 - 子狀態 or 子狀態機?與外部溝通!概念簡介: invoke services v.s. spawn actors in XState

先前我們介紹過了階層式狀態,讓我們能將一個狀態向下描述得更精確,比如以之前的 input 元件狀態機
當 input 是 changed 時,可以更向下描述,這個 changed 是 valid 或 invalid 的。

或者我們說 valid 、 invalid 唯有存在 changed 底下才是有意義的。
https://ithelp.ithome.com.tw/upload/images/20210929/20130721UvlbWhoZpj.png

情境簡介

然而現實的複雜情境中,階層狀態或許也會不堪使用,比如我想要製作一個 TODO List APP ,這個 List 我想擁有 loading / ready 的狀態...而 List 底下可有許多 TODO Item (0 - N)個,這個數量會隨使用者輸入而改變!

每個 TODO Item 可以有狀態:編輯中(editing)、預覽中(reading)、刪除(deleted);資料(延伸狀態):標題(title)、完成狀態(completed)
https://ithelp.ithome.com.tw/upload/images/20211012/20130721dhWtA85slL.png

如果我們將 TODO Item 視為 TODO LIST 的子狀態,我們要如何一開始就知道要寫幾組 todo 進入 machine config?而且每個 TODO Item 又有各自的狀態跟資料...

我們可以將 TODO Item 視為 TODO LIST 的子狀態機,然而這個 子狀態機 TODO Item 又必須要與 父狀態機 TODO LIST 進行狀態溝通及資料傳遞,比如說我按下全部完成,要讓所有的 TODO Item 被設定為已完成、按下刪除,要讓 TODO LIST 移除一個子狀態機 TODO Item 。

這裡採用的子狀態機是指能儲存狀態的 Serive,父子狀態機彼此的通訊及資料傳遞,也就是「Service」與「Service」間的訊息傳遞、互動。

這一類型「Service」的互動或者我們可以稱為「Actor」,已經有相當出名的理論支持!Actor Model:一種能保存內部狀態、與外部溝通,並且能建立其他 Service 的數學運算模型。

XState 提供兩種方式讓我們建立子狀態機

  1. Invoke(喚起、調用)
  2. Spawn(繁殖、生產)

兩者差別是 子狀態機 能不能在 父狀態機 的狀態之間共享;也就是 這個子狀態機 是活在某個特定狀態下之下 or 所有狀態下!

以底下 stackoveflow 的程式碼為 example

Invoke

這個被 invoke 的 child machine 就只存活在「pending」狀態裡,一離開「pending」child machine 就會結束服務。

// Machine 是 XState 舊版 API
const parentMachine = Machine({
  id: 'parent',
  initial: 'pending',
  states: {
    pending: {
      invoke: {
        src: childMachine
      }
    }
  }
});

Spawn

這個被 spawn 的 child machine 存活在所有的狀態裡,你看雖然範例命名不太好,它存放在 context 叫做 localOne ,但在其他的 state 都可以透過 context 拿到拿到這台名為 localOne 的 child machine 。

// Machine 是 XState 舊版 API
const parentMachine = Machine({
  id: 'parent',
  initial: 'waiting',
  context: {
    localOne: null
  },
  states: {
    waiting: {
      entry: assign({
        localOne: () => spawn(childMachine)
      })
    }
  }
});

建立子狀態機之外

Invoke 和 Spawn 也可以讓我們的狀態機與外部溝通,比如說我想等一個 promise 回來的資料或是某個 state 時我想執行某個 callback ,或者在某個狀態下,我想要建立 Observable 讓內外持續溝通。

參考資料


上一篇
Day26 - 使用 Guard 來實作一個馬克杯的狀態機
下一篇
Day 28 - XState in React (著重: local state)
系列文
From State Machine to XState31

尚未有邦友留言

立即登入留言