为什么这段Node.js readline处理代码输出空字典?该如何修复?
问题原因
- Node.js的readline模块事件监听是异步非阻塞逻辑,你注册
rl.on('line', callback)只是完成了事件回调的绑定,代码不会等待所有line事件触发完成再往下执行 - 你当前写在rl监听逻辑后面的
console.log(dict)执行时机远早于所有行读取、dict赋值操作,所以打印出来的自然是空对象 - 写在line回调内能正常打印,是因为每次行读取完成后才会触发回调执行,这时候对应行的字典数据已经完成赋值了
修复方案1:监听readline的close事件(原生回调写法)
把操作dict的逻辑放到close事件回调里,这时候所有行都已经读取处理完成了
const readline = require('readline'); const fs = require('fs'); let rl = readline.createInterface({ input: fs.createReadStream('Spanish.txt'), }) let dict={}; let arr1=[]; let arr2=[]; rl.on(`line`, (line)=>{ if (!line.startsWith('#')){ arr1=line.split('\t'); if (arr1[1]!=undefined) { arr2 = arr1[1].split('[').join(',').split('/'). join(',').split('(').join(',').split(','); dict[arr1[0]]=arr2[0]; } } }); // 监听读取完成事件 rl.on('close', () => { console.log(dict); // 后续对dict的所有操作都要放在这里面 })
修复方案2:Promise封装配合async/await写法
const readline = require('readline'); const fs = require('fs'); // 封装读取文件生成字典的异步方法 async function genDictFromFile(filePath) { const rl = readline.createInterface({ input: fs.createReadStream(filePath), }) const dict={}; let arr1=[]; let arr2=[]; for await (const line of rl) { if (!line.startsWith('#')){ arr1=line.split('\t'); if (arr1[1]!=undefined) { arr2 = arr1[1].split('[').join(',').split('/'). join(',').split('(').join(',').split(','); dict[arr1[0]]=arr2[0]; } } } return dict; } // 调用异步方法获取字典 genDictFromFile('Spanish.txt').then(dict => { console.log(dict); // 后续操作dict的逻辑写在这里 })
注:
for await...of遍历readline的用法需要Node.js版本 >= v11.14.0,低版本环境请使用方案1的close事件监听写法。
内容的提问来源于stack exchange,提问作者random math student
相关产品推荐
相关产品推荐

