JavaScript yield与异步编程

什么是 yield

yield 关键字只能在生成器函数中使用。生成器函数是一种特殊的函数,使用 function* 声明。当生成器函数执行到 yield 表达式时,它会暂停执行,并将 yield 后面的值返回给调用者。重要的是,函数的状态会被保存,以便稍后可以从暂停的地方继续执行。

生成器函数的基本语法:

javascript 复制代码
function* myGenerator() {
  yield 1;
  yield 2;
  yield 3;
}

const generator = myGenerator();

console.log(generator.next()); // { value: 1, done: false }
console.log(generator.next()); // { value: 2, done: false }
console.log(generator.next()); // { value: 3, done: false }
console.log(generator.next()); // { value: undefined, done: true }
  • function* myGenerator(): 声明一个生成器函数。
  • yield 1;: 暂停函数执行,并返回 1
  • generator.next(): 调用 next() 方法恢复函数的执行,并返回一个包含 valuedone 属性的对象。value 属性是 yield 表达式的值,done 属性表示生成器函数是否已经执行完毕。

双向通信
yield不仅能向外传递值,还能通过next(value)接收外部输入:

javascript 复制代码
function* calculator() {  
  const a = yield 'Enter a:'; 
  console.log(a)
  const b = yield 'Enter b:'; 
  console.log(b)
  return a + b;  
}  
const cal = calculator();  
cal.next();    // {value: 'Enter a:', done: false}  
cal.next(2);   // {value: 'Enter b:', done: false}  
cal.next(3);   // {value: 5, done: true}  

这种特性使得生成器可以动态响应外部逻辑

yield 的强大之处:

  1. 控制迭代过程: yield 允许你自定义迭代过程,按需生成值。这对于处理大型数据集或无限序列非常有用,可以避免一次性加载所有数据到内存中。

    javascript 复制代码
    function* infiniteSequence() {
      let i = 0;
      while (true) {
        yield i++;
      }
    }
    
    const sequence = infiniteSequence();
    
    console.log(sequence.next().value); // 0
    console.log(sequence.next().value); // 1
    console.log(sequence.next().value); // 2
    // ... 无限循环
  2. 实现状态机: yield 可以用于实现状态机,控制程序在不同状态之间的转换。

    javascript 复制代码
    function* stateMachine() {
      let state = 'start';
    
      while (true) {
        switch (state) {
          case 'start':
            console.log('Starting...');
            state = yield 'waiting';
            break;
          case 'waiting':
            console.log('Waiting for input...');
            state = yield 'processing';
            break;
          case 'processing':
            console.log('Processing data...');
            state = yield 'done';
            break;
          case 'done':
            console.log('Done!');
            return;
          default:
            console.log('Invalid state!');
            return;
        }
      }
    }
    
    const machine = stateMachine();
    console.log(machine.next()); // Starting... { value: 'waiting', done: false }
    console.log(machine.next('processing')); // Waiting for input... { value: 'processing', done: false }
    console.log(machine.next('done')); // Processing data... { value: 'done', done: false }
    console.log(machine.next()); // Done! { value: undefined, done: true }
相关推荐
Hy行者勇哥19 分钟前
HTML5 + 原生 CSS + 原生 JS 网页实现攻略
javascript·css·html5
小飞侠在吗5 小时前
vue props
前端·javascript·vue.js
DsirNg6 小时前
页面栈溢出问题修复总结
前端·微信小程序
小徐_23336 小时前
uni-app 也能远程调试?使用 PageSpy 打开调试的新大门!
前端·微信小程序·uni-app
大怪v6 小时前
【Virtual World 03】上帝之手
前端·javascript
招来红月8 小时前
记录JS 实用API
javascript
别叫我->学废了->lol在线等8 小时前
演示 hasattr 和 ** 解包操作符
开发语言·前端·python
霍夫曼8 小时前
UTC时间与本地时间转换问题
java·linux·服务器·前端·javascript
DARLING Zero two♡8 小时前
浏览器里跑 AI 语音转写?Whisper Web + cpolar让本地服务跑遍全网
前端·人工智能·whisper
꒰ঌ小武໒꒱9 小时前
文件上传全维度知识体系:从基础原理到高级优化
javascript·node.js