【问题标题】:Reading a file line by line and performing analyzes in node.js?逐行读取文件并在 node.js 中执行分析?
【发布时间】:2019-03-25 02:55:02
【问题描述】:

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

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);`打印所有行。因此,它不是按顺序执行的。我怎样才能确保在移动到下一行之前完成一行?

【问题讨论】:

  • 您不能将所有行读入一个数组并逐个分析吗?它不会等待的原因是 await 只会阻塞该函数,它不是正在读取的承诺链,您只是在事件处理程序中等待,读者怎么知道您想等待它?
  • 您目前使用readline 导入而不是一次性读取文件是否有原因?
  • @Icepickle 我刚刚发现它更容易逐行阅读。但是,任何将东西存储在数组中的解决方案对我来说都很好。

标签: javascript node.js


【解决方案1】:

readline 接口异步发出“on”事件,在其中一个事件中执行await 不会阻止其他事件被触发。相反,您可以像这样缓冲数组中的行:

r.on('line', url => urls.push(url));
r.on('close', async () => {
  for (const url of urls) {
    await analyzeAndSave(url);
  }
});

其中urls在创建readline接口之前被初始化为一个空数组。

【讨论】:

  • 这看起来确实是基于 OP 想要的,但是,我想需要提及 urls 变量应该在哪里,也许如果 readline 接口对读取文件有意义,如果你最终将它们分成一个大数组
【解决方案2】:

我认为这会对您有所帮助,此处举例说明。

Nodejs - read line by line from file, perform async action for each line and reusme

有人说你可以使用一个库来存储大文件,标题为:line-by-line

@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)
})

【讨论】:

    猜你喜欢
    • 2013-09-08
    • 2013-04-07
    • 1970-01-01
    • 2019-05-14
    • 2012-07-16
    • 2013-02-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多