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

如何在Node.js的for await readline异步迭代中添加用户提问功能

问题解决思路

核心问题原因

  • 你创建readline实例时设置了terminal: false,该配置会禁用rl.question()的交互提示输出,也会干扰输入流的正常回调
  • async生成器在for await循环执行break时,会自动调用生成器的return()方法终止迭代,你没有在生成器内做资源清理逻辑,导致readline接口持续挂起,看起来像break不生效
  • 你的生成器循环没有加数组边界判断,遍历完file.json的所有数据后会持续读取undefined条目
  • 你原来的退出答案里的quite是拼写错误,正确应为quit

修复后可运行实现

const readline = require('readline');
const { promisify } = require('util');

// 移除错误的terminal: false配置
const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout
});

const promptUserCLI = (q, exitAnswers = [], callback) => {
  rl.question(q, answer => {
    if (exitAnswers.includes(answer.toLowerCase())) {
      rl.close();
      return callback(new Error('user exit'));
    }
    callback(null, answer);
  });
};

const promptPromise = promisify(promptUserCLI)
const data = require('./file.json');

async function* gen() {
  let index = 0
  // 加finally块,生成器终止(break/报错)时自动关闭readline
  try {
    // 加数组边界判断,遍历完所有数据自动终止
    while (index < data.length) {
      const item = data[index]
      const answer = await promptPromise(`Make '${item.line}' [ [y]es/no/all/exit ]`, ['exit', 'quit'])
      index += 1
      yield { answer, item, index }
    }
  } finally {
    rl.close()
  }
}

// 测试逻辑,break可以正常退出
(async () => {
  try {
    for await (const item of gen()) {
      console.log('拿到的返回结果:', item)
      // 这里break会触发生成器的finally块,关闭rl后正常退出
      break
    }
    console.log('循环正常终止')
  } catch (e) {
    console.log('操作终止:', e.message)
  }
})()

补充说明

  • 如果你需要和原生readline的for await能力结合,不需要重写rl[Symbol.asyncIterator],直接在遍历每行的逻辑里调用promptPromise即可,按你的需求遍历自定义json数据,用独立的async生成器是更简洁的方案
  • 可以根据业务需要扩展gen生成器的逻辑,比如用户输入all的时候直接返回所有剩余条目,不需要逐个提问

内容的提问来源于stack exchange,提问作者Docky-Dockling

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 14:15:01