状态机是一种由状态、转移条件和动作组成的计算模型,任意时刻仅处于一个状态,如登录流程可用其建模。Generator函数通过yield暂停执行,适合用同步写法控制状态流转,如实现包含“未登录”“登录中”“已登录”“锁定”的认证状态机,每次调用next()传入事件触发状态切换,并返回当前状态,结合yield特性可清晰表达复杂状态逻辑,支持注入副作用,适用于工作流与UI导航等场景。

在 JavaScript 中,利用 Generator 函数和 yield 关键字可以非常优雅地实现一个复杂的状态机。Generator 能暂停和恢复执行的特性,天然适合表达状态流转。
什么是状态机?
状态机是一种计算模型,由一组状态、转移条件和动作组成。任意时刻只能处于一个状态,根据输入触发状态之间的切换。比如自动售货机、登录流程、游戏 AI 都可用状态机建模。
Generator 的核心优势
Generator 函数通过 *function 定义,使用 yield 暂停执行,每次调用 next() 才继续。这让我们可以用同步写法表达异步或分步逻辑,非常适合控制状态流转。
特点包括:
函数执行可中断,保留上下文通过 next(value) 向内部传值yield 表达式的返回值是 next() 传入的参数
实现一个带事件驱动的状态机
下面是一个模拟用户认证流程的状态机:包含“未登录”、“登录中”、“已登录”、“锁定”四种状态。
function* authStateMachine() { let state = 'idle'; let attempts = 0; const maxAttempts = 3; while (true) { const { type, password } = yield state; if (state === 'idle') { if (type === 'LOGIN') { if (password === 'secret') { state = 'authenticated'; } else { attempts++; if (attempts >= maxAttempts) { state = 'locked'; } else { state = 'pending'; } } } } else if (state === 'pending') { if (type === 'LOGIN') { if (password === 'secret') { state = 'authenticated'; } else { attempts++; if (attempts >= maxAttempts) { state = 'locked'; } } } } else if (state === 'authenticated') { if (type === 'LOGOUT') { state = 'idle'; attempts = 0; } } else if (state === 'locked') { if (type === 'RESET') { state = 'idle'; attempts = 0; } } }}
如何使用这个状态机
创建实例并驱动状态变化:
const machine = authStateMachine();console.log(machine.next().value); // 输出: idleconsole.log(machine.next({ type: 'LOGIN', password: 'wrong' }).value); // pendingconsole.log(machine.next({ type: 'LOGIN', password: 'wrong' }).value); // pendingconsole.log(machine.next({ type: 'LOGIN', password: 'wrong' }).value); // lockedconsole.log(machine.next({ type: 'RESET' }).value); // idleconsole.log(machine.next({ type: 'LOGIN', password: 'secret' }).value); // authenticated
每一步调用 next(input) 相当于发送一个事件,状态机根据当前状态和输入决定下一个状态,并通过 yield state 返回当前状态。
扩展思路:支持异步操作与副作用
可以在状态转移时插入副作用,比如记录日志、发请求等:
if (state === 'idle' && type === 'LOGIN') { console.log('正在验证...'); // 模拟异步验证 await new Promise(resolve => setTimeout(resolve, 100)); if (password === 'secret') { state = 'authenticated'; }}
注意:如果加入 async/await,就无法再用普通 Generator 控制。此时可结合 Thunk 或 Promise 包装器,或者改用 async generator(async function*)配合 for await...of 处理。
总结:Generator + yield 提供了一种线性、清晰的方式来编写复杂状态逻辑。相比一堆 if/else 或状态表,它更易读、易维护,尤其适合工作流、协议解析、UI 导航等场景。
基本上就这些。
以上就是如何使用 Generator 函数和 yield 关键字实现一个复杂的状态机?的详细内容,更多请关注创想鸟其它相关文章!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1527684.html
微信扫一扫
支付宝扫一扫