我有一个文件,我想一行一行地读取它,对于提取的每一行,我都会进行一些昂贵的分析,然后将结果保存到数据库中。简而言之,我有这样的事情:
const fs = require('fs');
const path = require('path');
const readline = require('readline');
async function analyzeAndSave(url) {
// Removed for brevity, but this function takes a minute or so finsh.
}
async function run() {
try {
const dataPath = path.join(path.dirname(require.main.filename), 'data/urls.txt');
const rl = readline.createInterface({
input: fs.createReadStream(dataPath),
});
let line_no = 0;
rl.on('line', async (url) => {
line_no++;
logger.info(`Analyzing: ${url}`);
await analyzeAndSave(url);
});
} catch (err) {
// Error caught.
logger.error(err);
}
}
run();
问题是,我注意到它不等待一行分析完成,而是尝试执行多个分析实例。我可以看到它最初是用logger.info('Analyzing: ' + url
;;打印所有行的。因此,它不会顺序执行。我如何确保一行完成后再移到下一行?
答案 0 :(得分:2)
readline接口正在异步发出“ on”事件,并且在其中一个事件中执行await
不会阻止其他事件被触发。相反,您可以像这样在数组中缓冲行:
r.on('line', url => urls.push(url));
r.on('close', async () => {
for (const url of urls) {
await analyzeAndSave(url);
}
});
其中urls
在创建readline接口之前被初始化为空数组。
答案 1 :(得分:1)
我认为这将对您有所帮助,此处示例和提及。
Nodejs - read line by line from file, perform async action for each line and reusme
有人说您可以使用一个大文件库,标题为:逐行
@JavierFerrero 提出了这样的解决方案。
var LineByLineReader = require('line-by-line'),
lr = new LineByLineReader('big_file.txt');
lr.on('error', function (err) {
// 'err' contains error object
});
lr.on('line', function (line) {
// pause emitting of lines...
lr.pause();
// ...do your asynchronous line processing..
setTimeout(function () {
// ...and continue emitting lines.
lr.resume();
}, 100);
});
lr.on('end', function () {
// All lines are read, file is closed now.
});
您还可以将其传递给屁股回调,等待操作完成 完成。
const fs = require('fs');
function run(path, cb) {
try {
fs.readFile(path, 'utf8', function(err, data){
if(err) throw err;
cb(data);
});
} catch (err) {
// Error caught.
}
}
run('./test.txt', (response) => {
// We are done, now continue
console.log(response)
})