如何使用async / await在node.js中异步创建creadReadStream

时间:2018-05-12 14:11:49

标签: node.js stream async-await

我无法使用fs.creadReadStream异步处理我的csv文件:

async function processData(row) {
    // perform some asynchronous function
    await someAsynchronousFunction();
}

fs.createReadStream('/file')
    .pipe(parse({
        delimiter: ',',
        columns: true
    })).on('data', async (row) => {
        await processData(row);
    }).on('end', () => {
        console.log('done processing!')
    })

我希望在createReadStream到达on('end')之前逐个读取每条记录后执行一些异步功能。

但是,on('end')会在我的所有数据完成处理之前被点击。有谁知道我可能做错了什么?

提前致谢!

2 个答案:

答案 0 :(得分:2)

.on('data, ...)不等待您的await。请记住,async函数会立即返回一个承诺,.on()没有注意到这个承诺,所以它只是继续快乐地继续。

await仅在函数内部等待,它不会阻止您的函数立即返回,因此流认为您已处理数据并不断发送更多数据并生成更多data事件

这里有几种可能的方法,但最简单的方法可能是暂停流直到processData()完成,然后重新启动流。

此外,processData()是否返回与异步操作完成相关联的承诺?这也是await能够完成工作所必需的。

readable stream doc包含在data事件期间暂停流然后在某些异步操作完成后恢复它的示例。这是他们的榜样:

const readable = getReadableStreamSomehow();
readable.on('data', (chunk) => {
  console.log(`Received ${chunk.length} bytes of data.`);
  readable.pause();
  console.log('There will be no additional data for 1 second.');
  setTimeout(() => {
    console.log('Now data will start flowing again.');
    readable.resume();
  }, 1000);
});

答案 1 :(得分:0)

我最近遇到了同样的问题。我通过使用一组承诺来修复它,并在.on("end")被触发时等待它们全部解决。

import parse from "csv-parse";

export const parseCsv = () =>
  new Promise((resolve, reject) => {
    const promises = [];
    fs.createReadStream('/file')
      .pipe(parse({ delimiter: ',', columns: true }))
      .on("data", row => promises.push(processData(row)))
      .on("error", reject)
      .on("end", async () => {
        await Promise.all(promises);
        resolve();
      });
  });