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

在 J*aScript 中,利用 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;
}
}
}
}如何使用这个状态机
创建实例并驱动状态变化:
小爱开放平台
小米旗下小爱开放平台
291
查看详情
const machine = authStateMachine();
console.log(machine.next().value); // 输出: idle
console.log(machine.next({ type: 'LOGIN', password: 'wrong' }).value); // pending
console.log(machine.next({ type: 'LOGIN', p
assword: 'wrong' }).value); // pending
console.log(machine.next({ type: 'LOGIN', password: 'wrong' }).value); // locked
console.log(machine.next({ type: 'RESET' }).value); // idle
console.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 关键字实现一个复杂的状态机?的详细内容,更多请关注其它相关文章!
# 是一个
# 阳江seo首页网站
# 银川建设网站哪家好
# 品牌边界营销推广方案
# 珠海360seo哪家好
# 南城服装网站优化哪里好
# 汕头网站建设制作
# 网站推广外包营销服务
# 重庆谷歌seo找谁做
# 成都的网络营销推广公司
# 青岛网站建设推广免费咨询
# 可以用
# 有哪些
# javascript
# 如何实现
# 如何用
# 可以使用
# 工作流
# 是一种
# 小爱
# 如何使用
# ai
# mac
# go
# java
# word
相关栏目:
【
科技资讯46185 】
【
网络学院92790 】
相关推荐:
Yandex搜索引擎一键访问入口_俄罗斯Yandex官网免登录
CSS布局中意外空白:解决padding-top导致的顶部间距问题
KFC早餐时段怎么领特惠代码_KFC早餐订餐优惠代码获取与使用说明
优化 Jest 模拟:强制未实现函数抛出错误以提升测试效率
如何使用Go和Martini动态服务解码后的图片
飞书妙记怎样用语音转文字速记_飞书妙记用语音转文字速记【速记方法】
Shopware订单对象中获取产品自定义字段的正确方法
将HTML Canvas内容转换为可上传的图像文件(File对象)
抖音隐秘迷城小游戏入口_ 抖音冒险解谜小游戏秒玩
LINUX怎么设置定时任务_LINUX crontab配置教程
Golang如何优化内存分配与垃圾回收_Golang内存管理与GC优化实践
Yandex官网免登录入口_俄罗斯Yandex搜索引擎一键访问
c++如何使用Meson构建系统_c++比CMake更快的构建工具
优化Django表单:提交验证失败后保留用户输入
PostgreSQL海量数据高效导入策略:Python与Django实践指南
Golang如何实现微服务鉴权与权限控制_Golang微服务鉴权与权限管理实践
高德地图公交到站提醒失败如何解决 高德提醒权限设置
《铁拳8》黑皮辣妹新实机:元气满满的18岁少女!
Highcharts 雷达图径向轴标签定制指南:利用多Y轴实现数值标注
微博网页版主页入口 微博官方网站免登录访问
反效果?《战地6》免费试玩开启后玩家数不升反降
J*a中实现Go语言select通道多路复用机制
Go语言中JSON数据解码与字段访问指南
Excel函数批量查找替换超快方法_Excel用REPLACE和FIND函数秒级替换
机器学习中对数变换预测结果的反向还原
深入理解J*a编译器的兼容性选项:从-source到--release
基于动态规划的房屋花卉种植最小成本算法详解
EMS快递官网app_中国邮政速递物流手机客户端
Eclipse怎么运行工程_Eclipse工程运行配置说明
Golang如何实现状态模式管理对象状态_Golang State模式实现技巧
win11专注助手在哪 Win11免打扰模式设置与自动化规则【指南】
在WordPress中通过REST API获取BasicAuth保护的远程文章
腾讯视频怎么举报不良内容_腾讯视频内容举报流程与违规信息处理方法
苹果手机如何防止被恶意App追踪
正确连接J*aScript到HTML实现可点击图片与自定义事件处理
红果短剧网页版官网入口 官方最新网址发布
KFC游戏互动怎么赢取优惠券_KFC线上游戏活动参与与优惠代码赢取教程
抓大鹅解压小游戏 抓大鹅摸鱼解压入口
学习通在线学习平台 学习通网页版直接进入课程中心
在命令行怎么运行html项目_命令行运行html项目方法【教程】
俄罗斯方块最新版入口 俄罗斯方块在线玩官网入口
在J*a中如何开发简易博客标签推荐系统_博客标签推荐项目实战解析
C++如何操作注册表_Windows平台下C++读写注册表的API函数详解
AO3官方可用镜像 Archive of Our Own网页版最新入口
优化大型XML文件解析:基于Python流式处理的内存高效方案
曝R星经典之作开发图 设计简陋但信息密集!
html网页设计源代码怎么运行_运行html网页设计源代码步骤【指南】
怎么在html里运行vbs脚本_html中运行vbs脚本方法【教程】
深入理解Go语言中的指针类型:以*string为例
msn官网入口地址手机版 msn官方网站手机最新链接


2025-10-08
浏览次数:次
返回列表
assword: 'wrong' }).value); // pending
console.log(machine.next({ type: 'LOGIN', password: 'wrong' }).value); // locked
console.log(machine.next({ type: 'RESET' }).value); // idle
console.log(machine.next({ type: 'LOGIN', password: 'secret' }).value); // authenticated