Node.js中如何让readline支持async/await异步Promise调用
问题诊断
你代码里一共存在3个核心问题:
1. await使用位置不符合语法规范
Node.js中只有两种场景可以直接使用await:
- 在标记了
async的函数内部 - 如果你使用ES模块规范(文件后缀为
.mjs,或package.json中配置"type": "module"),可以在文件顶层直接使用await
你当前代码是在CommonJS规范的脚本顶层直接写await,所以触发了语法错误。
2. Promise的resolve时机错误,会永远返回空结果
你在创建完readline实例后立刻执行了resolve(fresult),这时候文件流还没开始读取、line事件完全没有触发,fresult永远是空字符串。正确的做法是等readline读取完全部文件、触发close事件后再resolve结果,同时需要监听error事件处理文件读取失败的场景。
3. 正则重复构造的隐性问题
你调用grep函数时传入的已经是RegExp类型的正则对象,函数内部又执行了new RegExp(pattern),会导致正则被二次转义,匹配规则完全不符合预期。
修复后的完整代码
const fs = require('fs') const readline = require('readline') const grep = function(pattern, filepath){ return new Promise((resolve, reject)=>{ // 兼容正则对象和字符串类型的pattern const regex = pattern instanceof RegExp ? pattern : new RegExp(pattern); let fresult = []; const lineReader = readline.createInterface({ input: fs.createReadStream(filepath).on('error', reject) // 捕获文件读取错误 }); lineReader.on('line', function (line) { if(regex.test(line)){ fresult.push(line); // 用数组存储性能更好,避免字符串频繁拼接 } }); // 全部读取完成后再返回结果 lineReader.on('close', function () { resolve(fresult.join('\n')); }); lineReader.on('error', reject); }); } // 用async自执行函数包裹调用逻辑,解决顶层await的问题 (async () => { const filepath = '替换为你的日志文件实际路径'; let getLogs = await grep(/myregex/gi, filepath); console.log(getLogs); })()
可选优化方案
如果你想要更简单的顶层await使用方式,可以在项目的package.json中添加配置"type": "module",之后就可以直接在文件顶层写await,不需要包async自执行函数。
内容的提问来源于stack exchange,提问作者LeDucSAS
相关产品推荐
相关产品推荐

