JS使用lineReader逐行读文件时dbHost1无法获取dbHost2赋值问题
问题现象
当前实现代码如下:
async function rScript() { var dbHost1 = ''; var dbHost2; var DDD = await lineReader.eachLine(file, function(line) { if (line.includes('DB_HOST')) { dbHost2 = line.substr(18, 11); console.log('dbHost2', dbHost2); dbHost1 = dbHost2; } }); console.log('DDD', DDD) console.log('dbHost1', dbHost1); }
运行后控制台输出顺序和结果如下:
DDD { getReader: [Function: getReader] } dbHost1 dbHost2 'localhost'
逻辑中已经编写了dbHost1 = dbHost2的赋值语句,但最终dbHost1始终无法获取到dbHost2存储的数值。
根本原因
问题核心是*await没有等到逐行读取操作执行完成*:
- 你调用的
lineReader.eachLine方法返回值不是Promise,就是你打印出来的带getReader方法的普通对象,await关键字对非Promise类型的值不会产生阻塞等待效果,会直接同步执行后续代码。 - 逐行读取文件是异步IO操作,你传入
eachLine的回调函数会在文件IO完成、读到对应行的时候才触发执行。代码走到打印DDD和dbHost1的步骤时,逐行读取的回调还没执行到匹配DB_HOST的逻辑,dbHost1还是初始的空字符串,所以打印为空。 - 等两个前置console执行完之后,逐行读取的回调才跑完,打印出
dbHost2 'localhost',这时候赋值操作才真正执行,早就过了你读取dbHost1值的时机。
修复方案
不要直接给非Promise返回值的eachLine加await,需要把逐行读取逻辑包装成可等待的Promise,等所有行遍历完成、赋值结束后再读取dbHost1的值,参考写法(以Node.js原生readline模块为例):
const fs = require('fs'); const readline = require('readline'); async function rScript() { let dbHost1 = ''; // 创建逐行读取接口 const rl = readline.createInterface({ input: fs.createReadStream(file), crlfDelay: Infinity }); // 用for await...of 逐行遍历,会自动等待每一行读取完成 for await (const line of rl) { if (line.includes('DB_HOST')) { const dbHost2 = line.substr(18, 11); console.log('dbHost2', dbHost2); dbHost1 = dbHost2; // 找到目标值后可以直接终止遍历,不需要读剩下的内容 break; } } console.log('dbHost1', dbHost1); // 这里就能正常拿到localhost了 }
如果你用的是第三方line-reader包,也可以自己手动包装成Promise,在遍历结束的回调里resolve结果即可。
内容的提问来源于stack exchange,提问作者Shawn
相关产品推荐
相关产品推荐

