js yield暂停执行

2026-05-12 02:00:24 294阅读 0评论

代码跑不动了?聊聊 JS 中那个让函数“喘口气”的 yield

前端开发里常遇到这种情况:任务太耗时,界面卡死;或者数据流太长,想分步骤处理。传统的回调地狱或单纯的 Promise 链式调用,有时候还是不够灵活。这时候,JavaScript 里的生成器(Generator)就派上了用场,而核心中的核心,就是那个能让代码按下的“暂停键”——yield

很多人听到 yield 就头疼,觉得它玄乎。其实把它想象成视频播放器里的“暂停”就好理解了。普通的函数像是一条直跑道,从第一行跑到最后一行,中途不能停。但用了 function* 定义的生成器函数,中间可以设无数个检查点。

看这段最基础的结构:

function* count() {
  console.log('开始');
  const step1 = yield 1;
  console.log('拿到值:', step1);
  const step2 = yield 2;
  console.log('拿到值:', step2);
}

注意到关键字前的星号了吗?这是开启暂停模式的开关。当你调用 count() 时,函数并不会立即执行内部代码,而是返回一个迭代器对象。只有当你在外部调用 .next() 方法,执行线才真正推进到第一个 yield 处。

这就是 yield 的第一个魔法:挂起当前状态。代码停在 yield 1 这里,后面的逻辑还没跑,甚至局部变量都保持着冻结状态。对于需要长流程控制来说,这意味你可以在两步之间插入大量业务逻辑,比如等待用户点击、查询缓存或者上报日志,而不必把整个大函数拆得支离破碎。

搞懂了停歇,自然要谈谈如何唤醒。每次调用 .next(),不仅会恢复运行,还能带着新的参数进来。这是一个双向通信的过程。刚才代码里的 step1,实际上接收的就是下一次调用 .next(值) 时传入的参数。这种机制特别适合做状态机,每一步的输出是下一步的输入,上下文信息流转非常清晰。

不过要注意个细节,第一次调用 next 必须不带参。因为函数刚开始执行,根本没法接收 yield 左边的返回值。等到第二次、第三次调用,你就可以通过传参来动态改变生成器内部的流向。

当然,现在有了 async/await,很多人觉得生成器过时了。其实不然。async/await 本质上是 generator + promise 的语法糖封装。如果你需要在 Promise 无法完全覆盖的场景下精细化控制流程,比如手动管理一个庞大的数据分页迭代,或者构建一个可插拔的工作流引擎,原生 yield 提供的底层控制力依然无可替代。它不依赖任何外部库,纯粹靠语言特性实现惰性求值。

内存方面也有优势。处理十万条数据列表时,你不需要一次性在内存塞满数组。用 yield 一个个吐出数据,处理完即释放,大大降低了峰值内存占用。这对移动端性能优化尤为关键。

写到这里,你会明白 yield 不仅仅是暂停。它是为了把原本线性的执行逻辑,变成可控的、可干预的状态流转。掌握它,意味着你能在不改变主逻辑架构的前提下,随意插入断点观察、修改数据或延迟计算。

下次遇到那种“中间必须停下来等等人,再继续往下走”的需求,别急着硬拆函数。试着给函数加个星号,放个 yield,让代码学会呼吸,反而能跑得更稳。

文章版权声明:除非注明,否则均为Dark零点博客原创文章,转载或复制请以超链接形式并注明出处。

发表评论

快捷回复: 表情:
验证码
评论列表 (暂无评论,294人围观)

还没有评论,来说两句吧...

目录[+]