状态机通过定义状态、事件和转移规则来管理对象行为变化。在JavaScript中可用对象实现,如电灯开关有’off’和’on’状态,响应’push’事件切换;进一步可封装为工厂函数createStateMachine,支持初始化、转移和回调,用于订单流程等场景;还可扩展钩子函数onEnter/onExit,实现登录流程中的提示与副作用处理,提升可维护性与扩展性。

状态机是一种处理对象行为随状态变化而改变的编程模型。在JavaScript中实现一个简单的状态机,可以帮助我们更好地管理组件或对象的复杂状态流转,比如按钮的启用/禁用、页面流程控制等场景。核心思路是:定义状态、定义事件、明确状态如何响应事件进行转移。
1. 状态机的基本结构
一个最简状态机包含三个要素:当前状态(currentState)、允许的状态集合、以及状态转移规则(transitions)。我们可以用对象来描述这些规则,让代码清晰且易于维护。
例如,设计一个电灯开关的状态机:
状态有:’off’ 和 ‘on’事件有:’push’(按下开关)规则:’off’ + ‘push’ → ‘on’;’on’ + ‘push’ → ‘off’
基于此,可以写出如下实现:
立即学习“Java免费学习笔记(深入)”;
const lightSwitch = { currentState: 'off', transitions: { off: { push: 'on' }, on: { push: 'off' } }, // 触发事件的方法 trigger(event) { const nextState = this.transitions[this.currentState][event]; if (nextState) { this.currentState = nextState; console.log(`状态切换为: ${this.currentState}`); } else { console.warn(`不允许的事件 "${event}" 在状态 "${this.currentState}" 下`); } }};// 使用示例lightSwitch.trigger('push'); // 输出:状态切换为: onlightSwitch.trigger('push'); // 输出:状态切换为: off
2. 封装为可复用的函数
为了提升复用性,我们可以将状态机抽象成一个工厂函数,传入配置即可生成不同的状态机实例。
function createStateMachine(config) { return { currentState: config.initial, transitions: config.transitions, trigger(event) { const currentState = this.currentState; const nextState = this.transitions[currentState]?.[event]; if (nextState) { this.currentState = nextState; // 可选:执行状态变更后的回调 if (typeof config.onChange === 'function') { config.onChange(currentState, nextState, event); } } else { console.warn(`无效转移: ${currentState} --${event}-> ${nextState}`); } } };}
使用这个工厂创建一个订单状态机:
const orderMachine = createStateMachine({ initial: 'pending', transitions: { pending: { pay: 'paid', cancel: 'canceled' }, paid: { ship: 'shipped', refund: 'refunded' }, shipped: { deliver: 'delivered' }, canceled: {}, refunded: {}, delivered: {} }, onChange(from, to, event) { console.log(`订单从 "${from}" 经 "${event}" 变为 "${to}"`); }});// 模拟操作orderMachine.trigger('pay'); // 输出:订单从 "pending" 经 "pay" 变为 "paid"orderMachine.trigger('ship'); // 输出:订单从 "paid" 经 "ship" 变为 "shipped"orderMachine.trigger('deliver'); // 输出:订单从 "shipped" 经 "deliver" 变为 "delivered"
3. 添加状态进入/退出的钩子
在实际开发中,状态切换时常需要执行副作用,比如发送请求、更新UI。可以在状态机中加入钩子函数(hooks),增强扩展能力。
改进版:支持每个状态定义 onEnter 和 onExit
function createStateMachineWithHooks(config) { let currentState = config.initial; function getStateConfig(state) { return config.states?.[state] || {}; } return { trigger(event) { const nextState = config.transitions?.[currentState]?.[event]; if (!nextState) { console.warn(`不允许的事件 "${event}" 在状态 "${currentState}"`); return; } // 执行当前状态的退出逻辑 const currentConfig = getStateConfig(currentState); currentConfig.onExit && currentConfig.onExit(); // 切换状态 const previous = currentState; currentState = nextState; // 执行新状态的进入逻辑 const nextConfig = getStateConfig(nextState); nextConfig.onEnter && nextConfig.onEnter(previous); // 外部监听 config.onChange && config.onChange(previous, nextState, event); }, getState() { return currentState; } };}
示例:带提示的用户登录流程
const loginMachine = createStateMachineWithHooks({ initial: 'idle', states: { idle: { onEnter: () => console.log('等待用户操作...') }, loading: { onEnter: () => console.log('正在登录...'), onExit: () => console.log('登录请求完成') }, success: { onEnter: () => console.log('登录成功!欢迎回来') }, error: { onEnter: (from) => console.log(`从 ${from} 登录失败`) } }, transitions: { idle: { login: 'loading' }, loading: { resolve: 'success', reject: 'error' }, success: {}, error: { retry: 'idle' } }});loginMachine.trigger('login'); // 进入 loadingloginMachine.trigger('resolve'); // 进入 success
基本上就这些。通过这种模式,你可以把复杂的条件判断转化为清晰的状态流转,代码更易读、更健壮。尤其适合表单流程、游戏角色行为、UI交互控制等场景。不复杂但容易忽略的是:定义好边界和非法转移,避免状态失控。
以上就是使用JavaScript实现一个简单的状态机_js编程思想的详细内容,更多请关注创想鸟其它相关文章!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1533847.html
微信扫一扫
支付宝扫一扫