Skip to content

aifsmjs — 狀態機

This content is not available in your language yet.

import { Aside } from ‘@astrojs/starlight/components’;

aifsmjs 是一個小型、嚴格的 FSM(有限狀態機)函式庫。核心哲學是定義與實作分離:狀態圖是純 JSON 資料,guards/actions/effects 在 runtime 注入,因此整個 machine definition 可以被序列化、跨 Worker 傳輸,或存進資料庫。

生命週期是一個純函數:step() 按固定順序執行 guards → exit → action → entry,不可中斷、可確定性重放。

Terminal window
pnpm add aifsmjs
import { setup, createRuntime, assign } from "aifsmjs";
type Ctx = { ticks: number };
type Evt = { type: "NEXT" };
// 1. 定義是純資料:setup<Ctx, Evt>() 讓 States 從 states 的 key 自動推斷
const trafficLight = setup<Ctx, Evt>().defineMachine({
id: "trafficLight",
initial: "red",
context: { ticks: 0 },
states: {
red: { on: { NEXT: { target: "green", actions: ["bump"] } } },
green: { on: { NEXT: { target: "yellow", actions: ["bump"] } } },
yellow: { on: { NEXT: { target: "red", actions: ["bump"] } } },
},
});
// 2. 實作在 runtime 注入
const runtime = createRuntime(trafficLight, {
actions: {
bump: assign(({ context }) => ({ ticks: context.ticks + 1 })),
},
});
// 3. 發送事件
runtime.send({ type: "NEXT" });
console.log(runtime.getSnapshot().value); // "green"
console.log(runtime.getSnapshot().context); // { ticks: 1 }
MachineDefinition(純資料)+ Implementations(runtime 注入)
step(def, snapshot, event, impl)
→ guards → exit → action → entry
→ 回傳新 snapshot(不可變)
Subpath用途
aifsmjs核心:setupcreateRuntimeassignstep
aifsmjs/guardsandornot guard 組合器
aifsmjs/effects副作用雙軌道 enq.effect()
aifsmjs/inspectKoa-style 只觀察、不修改轉移的 middleware
aifsmjs/replay事件序列回放
aifsmjs/pbtfast-check fc.commands 整合,屬性測試
aifsmjs/timertick-based timer hooks
  • 遊戲場景切換:FSM 管理 lobby → game → paused → gameOver,emit 事件到渲染層
  • 多步驟表單:每個步驟是一個 state,guards 驗證欄位再允許 NEXT 轉移
  • aiecsjs 搭配:ECS 裡的 entity 可以帶一個 FSM snapshot 管理行為狀態(例如角色的 idle / walk / attack
  • aibridgejs 搭配:machine definition 可直接 JSON 序列化後透過 bridge 傳到另一個 context