状态机是用有限状态建模业务流程的可靠方式,适用于多步骤、有分支、需回退或条件跳转的复杂逻辑,核心是将“当前做什么”抽象为“当前状态”,明确事件触发、状态切换及对应动作。

状态机是用有限状态来建模业务流程的可靠方式,特别适合处理多步骤、有分支、需回退或条件跳转的复杂逻辑,比如表单提交流程、订单状态流转、游戏角色行为、审批工作流等。核心在于把“当前做什么”抽象成“当前处于什么状态”,再明确“什么事件触发状态切换”以及“切换时执行什么动作”。
用对象字面量定义状态和转移规则
最轻量也最常用的方式是用一个对象描述所有状态,每个状态对应一个函数或配置项,包含进入动作、可响应的事件、目标状态和离开动作。
例如实现一个简单的登录流程状态机:
const loginMachine = {
initial: 'idle',
states: {
idle: {
on: { CLICK_LOGIN: 'checking' }
},
checking: {
on: {
SUCCESS: 'success',
FAILURE: 'error',
TIMEOUT: 'idle'
}
},
success: {
on: { LOGOUT: 'idle' }
},
error: {
on: { RETRY: 'checking', CLOSE: 'idle' }
}
}
};
配合一个简易运行器,就能驱动状态迁移并执行副作用(如发请求、更新 UI):
- 维护当前 currentState
- 提供 send(event, payload) 方法,根据当前状态查
on映射,找到目标状态 - 执行进入新状态前的清理、进入后的初始化(如
enter/exit钩子) - 支持携带数据(
payload)传递上下文,比如错误信息、用户 token
用类封装状态机,支持嵌套与历史记录
当流程变深(如“编辑草稿 → 提交审核 → 审核中 → 驳回/通过 → 发布”),纯配置难以管理。此时建议用 class 封装,显式管理状态栈、支持撤销、记录迁移日志。
- 内部用 Map 存储状态处理器,每个处理器返回新状态或 Promise(支持异步操作)
- 添加 history 数组记录每次迁移:
{ from, to, event, timestamp } - 实现 goBack():弹出最近一次迁移,回到上一状态,并触发
exit和enter - 允许状态处理器返回
{ state: 'xxx', data: {...} },让数据随状态流动,避免全局变量
结合 React 实现声明式状态流
在组件中使用状态机,关键是把状态机实例与组件生命周期对齐,并让 UI 只依赖当前状态。
- 用 useReducer 模拟状态机 reducer:每个 action type 对应一个事件,reducer 根据当前 state + action 返回新 state
- 或用 useMachine(XState 库):写 JSON 描述状态图,自动处理并发、延时、服务调用、条件分支
- UI 层只做“状态映射”:
switch (state.value) { case 'loading': return <spinner></spinner>; ... } - 事件触发统一走
service.send({ type: 'SUBMIT' }),不直接改 state,保证流程可控
处理真实场景中的关键细节
实际项目里,状态机容易在边界处失控。几个必须考虑的点:
-
非法事件拦截:在
send中校验当前状态是否允许该事件,否则静默丢弃或抛错,防止误触发 -
异步状态保持:如“提交中”状态不能被重复点击,应在进入
submitting时禁用按钮,且 send 后立即锁定,成功/失败后再解锁 -
状态持久化:刷新页面后恢复到上次状态,可将
currentState和必要context存入 localStorage,启动时读取 - 调试可视化:打印迁移日志,或集成 XState Visualizer,实时看到状态图和当前高亮节点
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











