首页 > web前端 > js教程 > 正文

如何使用 Generator 函数和 yield 关键字实现一个复杂的状态机?

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

如何使用 generator 函数和 yield 关键字实现一个复杂的状态机?

在 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;
      }
    }
  }
}
登录后复制

如何使用这个状态机

创建实例并驱动状态变化:

腾讯智影-AI数字人
腾讯智影-AI数字人

基于AI数字人能力,实现7*24小时AI数字人直播带货,低成本实现直播业务快速增增,全天智能在线直播

腾讯智影-AI数字人73
查看详情 腾讯智影-AI数字人
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', password: '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 generatorasync function*)配合 for await...of 处理。

总结:Generator + yield 提供了一种线性、清晰的方式来编写复杂状态逻辑。相比一堆 if/else 或状态表,它更易读、易维护,尤其适合工作流、协议解析、UI 导航等场景。

基本上就这些。

以上就是如何使用 Generator 函数和 yield 关键字实现一个复杂的状态机?的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习
PHP中文网抖音号
发现有趣的

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号