当前位置: 首页 > news >正文

关于 Babel 编译后的 Generator 状态机结构解析

一、为什么 Babel 要编译成 Generator?

老版本浏览器不支持 async/await,所以 Babel 会:

async function fn() {                      // 定义一个异步函数 fn,使用 async 关键字表明函数内部可以使用 awaitconst res = await getData();            // 调用异步函数 getData(),等待其执行完成后,将返回值赋给 res 变量return res + 1;                         // 返回 res 加 1 的结果;这个 return 的结果会自动被封装成一个 Promise 对象
}

编译成:

var fn = _asyncToGenerator(                    // 调用 _asyncToGenerator 把一个 Generator 函数转成支持 Promise 的 async 函数regeneratorRuntime.mark(function* _callee() { // 使用 regeneratorRuntime.mark 包装一个 Generator 函数,生成器函数名为 _calleevar res;                                   // 定义变量 res,用于存放 getData 的返回结果return regeneratorRuntime.wrap(function (_context) { // 包装内部状态控制逻辑(状态机),_context 管理执行流程while (1) switch (_context.prev = _context.next) { // 状态机循环,通过 switch 和 _context 控制流程跳转case 0:                                 // case 0:初始状态_context.next = 2;                    // 跳转到状态 2,并执行 yield 表达式(实际是 await)return getData();                     // yield getData(),此处暂停,等待 Promise 返回(相当于 await getData())case 2:                                 // case 2:getData 执行完成,结果通过 _context.sent 获取res = _context.sent;                  // 把 yield 表达式(即 getData())的返回值赋给 res_context.abrupt("return", res + 1);   // 立即中断函数并返回 res + 1,相当于 return res + 1}}, _callee);                                // 绑定到 _callee 生成器函数上})
);

二、结构总览(模块分解)

编译后核心结构包括这几个部分:

名称解释
_asyncToGenerator()把 Generator 包装成异步 Promise
regeneratorRuntime.mark(fn)把函数标记为 Generator
regeneratorRuntime.wrap(fn)把函数包裹成状态机控制结构
while (1) switch(...)状态切换结构
_context.next跳转到下一个状态
_context.sent获取上一个 yield/await 的返回值
_context.abrupt()立即返回或退出当前状态

三、状态机结构详解

源码:

async function test() {const a = await getData();const b = await parseData(a);return b;
}

编译后:

var test = _asyncToGenerator(                // _asyncToGenerator:将生成器函数转换为返回 Promise 的函数(兼容 async)regeneratorRuntime.mark(function* () {     // regeneratorRuntime.mark:将匿名 Generator 函数进行注册和标记var a, b;                                // 定义两个变量 a 和 b,用来存储异步操作的结果return regeneratorRuntime.wrap(function (_context) { // 包装状态机,_context 是内部上下文控制器while (1) switch (_context.prev = _context.next) { // 无限循环 + 状态切换机制(状态机)case 0:                              // 初始状态 case 0_context.next = 2;                 // 设置下一步跳转到 case 2,同时 yield 一个异步操作return getData();                  // yield getData(),相当于 await getData(),暂停执行等待结果case 2:                              // 等 getData() Promise resolve 后,跳转到这里a = _context.sent;                 // 获取 getData() 的结果,赋值给变量 a_context.next = 5;                 // 设置下一步为 case 5return parseData(a);               // yield parseData(a),等价于 await parseData(a)case 5:                              // 等 parseData() 执行完后跳到这里b = _context.sent;                 // 获取 parseData(a) 的结果,赋值给变量 b_context.abrupt("return", b);      // 立即中断并返回 b,等价于 return b}});})
);

四、状态转移图解

状态是通过 switch (_context.prev = _context.next) 控制的:

状态 0 → _context.next = 2return getData();          // await getData()状态 2 → a = _context.sent_context.next = 5return parseData(a);   // await parseData(a)状态 5 → b = _context.sentreturn b;              // return 结果

每个 case 就是一个逻辑步骤。每次 return 表示 await每次 sent 是拿返回值


五、关键语句详解

语句作用等价于原始 JS
_context.next = N; return foo();执行 foo,并跳转到第 N 步await foo();
res = _context.sent;拿到上一步 yield 的结果const res = await xxx;
_context.abrupt("return", xxx);提前退出函数,返回值为 xxxreturn xxx;

六、执行流程详解(配图思维)

async function fn() {const res = await getData(); // Step 1await saveData(res);         // Step 2return "done";               // Step 3
}

变成:

switch (_context.prev = _context.next) {       // 状态机入口,切换执行状态case 0:                                       // 第 0 步,初始状态_context.next = 2;                          // 指定下一步为 case 2return getData();                           // step 1:执行 getData(),暂停函数等待 Promise 结果(相当于 await getData())case 2:                                       // 第 2 步,getData() 执行完,继续执行res = _context.sent;                        // 获取 getData() 的结果,赋值给 res(相当于 const res = await getData())_context.next = 5;                          // 指定下一步为 case 5return saveData(res);                       // step 2:执行 saveData(res),暂停函数等待 Promise 结果(相当于 await saveData(res))case 5:                                       // 第 5 步,saveData(res) 执行完,继续执行_context.abrupt("return", "done");          // step 3:返回 "done",终止 Generator(相当于 return "done")
}

每一步是状态跳转 + 执行 + 下一步


七、如何手动还原 async/await?

只需 3 步

  • _context.next = N; return xxx → 就是 await xxx

  • xxx = _context.sent; → 表示上一步结果赋值

  • _context.abrupt("return", ...) → 函数的 return


八、技巧总结

实战分析点如何应对
_context.sent找到结果变量,理解 await 获取值
_context.next理解跳转执行顺序
abrupt("return")确定退出函数并返回值
多层嵌套 Generator拆解并逐步打印每层函数

相关文章:

  • 做面包网站品牌推广活动策划案例
  • 12306网站为什么做不好使今天大事件新闻
  • 婚纱网站页面设计网站seo快速优化
  • 网站装修用什么软件做免费推广软件哪个好
  • 黄金网站app软件下载安装在线网站排名工具
  • 如何黑网站常用的搜索引擎有
  • 数据赋能(319)——安全与合规——数据安全可控
  • 美团小程序闪购 mtgsig1.2
  • 第三节 布局与盒模型-盒模型与box-sizing
  • 【二】19.关于LCD和LTDC
  • 从零搭建共享棋牌室物联网系统:硬件选型与避坑指南!
  • 发布 npm 包完整指南(含账号注册、发布撤销与注意事项)
  • 文件锁的艺术:深入解析 `fcntl(F_SETLK/F_GETLK)`
  • C# WinForms 日志实现与封装
  • Flink状态和容错-基础篇
  • Golang Kratos 系列:领域层model定义是自洽还是直接依赖第三方(三)
  • 帮助装修公司拓展客户资源的微信装修小程序怎么做?
  • 重点解析(软件工程)
  • MonkeyOCR在Win习题部署指南和报错提醒
  • 谷歌 Gemini 2.5 系列模型:性能、功能与应用全方位解析​
  • 深入理解RAG:大语言模型时代的知识增强架构
  • pyqt多界面
  • 人机协作新篇章:艾利特按摩机器人如何重塑健康生活
  • 【JS】整理常复用的JS函数合集
  • python有哪些常用的GUI(图形用户界面)库及选择指南
  • SpringCloud系列(34)--使用Hystrix进行服务熔断