You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaScript生成器函数中条件yield的执行问题排查

问题分析与解决方案

问题根源

你的代码主要有三个核心问题,导致RL-type的标题无法正确生成:

  • 生成器循环逻辑错误:CommentGenerator里的while(typeof v !== 'undefined')循环一旦进入,就会一直输出同一个RL标题。因为生成器内部的v变量只会保留第一次next(r)传入的值,后续next()传进来的新值不会更新这个变量,循环也就无法输出新的标题。
  • 调用逻辑匹配错误:你现在对每一行RL类型的内容都调用gen.next(r),但实际上每个RL组(比如RL1开头的所有行)只需要输出一次标题,而且初始r=3也不符合预期输出从RL1开始的要求。
  • 阶段划分不清晰:生成器没有明确区分「输入/层阶段」「随机层阶段」「输出阶段」,导致无法在正确的时机切换标题输出逻辑。

修正后的代码

调整生成器函数

重写CommentGenerator,让它能清晰接收RL组编号、切换阶段:

function* CommentGenerator() {
  // 输出固定的输入和层标题
  yield '# Input 1\n';
  yield '';
  yield '';
  yield '# Layer 1\n';
  yield '';
  yield '# Layer 2\n';
  
  // 等待接收RL组编号,直到传入null结束RL阶段
  let receivedValue;
  while ((receivedValue = yield) !== null) {
    // 收到组号后,输出对应的RL标题
    yield `# RLayer ${receivedValue}\n`;
  }
  
  // RL阶段结束,输出输出层标题
  yield '# Output 1\n';
  // 后续一直输出空行
  while(true) {
    yield '';
  }
}

调整调用逻辑

修改PrintStuff函数,跟踪RL组的变化,只在新组出现时触发标题输出,并正确切换阶段:

function PrintStuff() { 
  var gen = CommentGenerator(); 
  var out = ''; 

  // 先走完生成器的固定初始标题部分
  let result;
  do {
    result = gen.next();
    out += result.value;
  } while (!result.done && !result.value.includes('# Layer 2'));

  // 初始化数据数组
  var lines = ['I1', 'I1.1', 'I1.2', 'L1', 'L1.2', 'L2']; 
  // 随机添加RL类型数据
  const rlCount = Math.floor(Math.random() * 10) + 1;
  for(let i = 1; i <= rlCount; i++) { 
    lines.push(`RL${i}`); 
    lines.push(`RL${i}.1`); 
    lines.push(`RL${i}.2`); 
    lines.push(`RL${i}.3`); 
  } 
  // 添加输出类型数据
  lines.push('O10'); 
  lines.push('O10.1'); 
  lines.push('O10.2'); 

  let currentRLGroup = null;
  let rlNumber = 1; // 从RL1开始计数

  for(let i = 0; i < lines.length; i++) { 
    const line = lines[i]; 
    if(line.startsWith('RL')) {
      // 提取当前RL的组号(比如RL1.1的组号是1)
      const group = line.match(/RL(\d+)/)[1];
      if (group !== currentRLGroup) {
        // 遇到新的RL组,先推进生成器到接收值的位置,再传入组号获取标题
        gen.next();
        out += gen.next(rlNumber).value;
        currentRLGroup = group;
        rlNumber++;
      } else {
        // 同一组的子行,输出空行
        out += gen.next().value;
      }
      out += `${line}\n`;
    } else if(line.startsWith('O')) {
      // 进入输出阶段,通知生成器结束RL阶段
      gen.next(null);
      // 获取输出标题
      out += gen.next().value;
      out += `${line}\n`;
      // 处理剩余的O类型子行
      for (let j = i + 1; j < lines.length; j++) {
        out += gen.next().value;
        out += `${lines[j]}\n`;
      }
      break; // 已处理完所有O行,跳出循环
    } else {
      // I/L类型行,输出空行+内容
      out += gen.next().value;
      out += `${line}\n`;
    }
  } 
  console.log(out) 
}

PrintStuff();

关键改动说明

  1. 生成器的阶段化设计:把生成器分成三个明确阶段,通过yield接收参数来切换RL阶段的输出,用null标记RL阶段结束,进入输出阶段。
  2. RL组跟踪:在调用端通过正则提取RL组号,只在新组出现时才触发生成器输出标题,避免重复输出。
  3. 初始阶段预执行:先把生成器的固定标题部分执行完,再开始处理数据行,确保初始标题顺序正确。

这样运行代码就能得到你想要的预期输出了。

内容的提问来源于stack exchange,提问作者Swiffy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 21:02:38