在Node.js中逐行异步处理文件

时间:2018-10-21 11:20:03

标签: javascript node.js

此答案Read a file one line at a time in node.js?显示了如何逐行读取文件。

var lineReader = require('readline').createInterface({
  input: require('fs').createReadStream('file.in')
});

lineReader.on('line', function (line) {
  console.log('Line from file:', line);
});
lineReader.on('close', function (line) {
  console.log('Finished');
});

但是,如果我将该回调函数设为async函数,以便我可以执行诸如验证和转换每一行并将其写入不同文件或API的操作,那么它将无法正常工作。无需等待各行完成其异步功能即可触发“关闭”事件。

是否可以使用readline或Node.js内置的任何库逐行异步处理文件?

最简单的方法是什么?

我需要逐行执行此操作,因为文件非常大,否则将完全消耗内存。

2 个答案:

答案 0 :(得分:0)

不要使用async function作为回调,事件发射器不会在意返回的诺言。相反,您可以自己构建一个承诺链:

var lineReader = require('readline').createInterface({
  input: require('fs').createReadStream('file.in')
});
var done = Promise.resolve();

lineReader.on('line', function (line) {
  console.log('Line from file:', line);
  var promise = validate(line).then(transform); // or whatever;
  done = Promise.all([
    done
    promise
  ]).then(() => void 0); // needed to drop result data
  // alternatively also do things that must happen sequentially
});
lineReader.on('close', function (line) {
  console.log('Finished reading');
  done.then(() => console.log('Finished transforming'));
});

答案 1 :(得分:0)

this answer中所述,应该对流进行承诺化并将其转换为异步迭代器,以便有效地对promise和async..await进行迭代。这可以通过第三方p-event库来实现:

try {
    const lineReader = require('readline').createInterface({
      input: require('fs').createReadStream('file.in')
    });

    const asyncIterator = pEvent.iterator(lineReader, 'line', {
      resolutionEvents: ['close']
    });

    for await (const line of asyncIterator) {
      console.log('Line from file:', line);
    }
} catch(e) {
    console.log(e);
} finally {
  console.log('Finished');
}