逐行读取文件并在node.js中执行分析?

时间:2019-03-24 15:31:44

标签: javascript node.js

我有一个文件,我想一行一行地读取它,对于提取的每一行,我都会进行一些昂贵的分析,然后将结果保存到数据库中。简而言之,我有这样的事情:

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 ;;打印所有行的。因此,它不会顺序执行。我如何确保一行完成后再移到下一行?

2 个答案:

答案 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)
})