在NodeJS中使用转换/双工流

时间:2018-10-13 08:41:59

标签: javascript node.js json csv

我正在使用NodeJS(贵族模块)从外部源(低功耗蓝牙)收集数据。我将它们流式传输到外部文件中的JSON数组。我们从Source.json来称呼它。看起来像这样:

fromSource.json

[
     {
         "id": 1,
         "name": "foo"
         "value": 123
     },
     {
         "id": 2,
         "name": "foo2",
         "value": 123
     },
     {
         "id": 3,
         "name": "foo3",
         "value": 789
     }
]

另一方面,我将实时处理这些对象并将新值存储在CSV文件中。让我们将其称为Destination.csv。看起来像这样:

toDestination.csv

id,name,convertedValue
1,"foo",123000
2,"foo2",456000
3,"foo3",789000

每隔一秒钟,我将从源接收一个新值(一个新的json对象),将其推入可写流(json数组文件),然后将其读入可读流,进行转换,然后再次将其写入最终目标文件csv文件。

我的问题是:NodeJS流是否适合处理JSON对象?使用它们之前我应该​​先对它们进行分类处理吗?在我的情况下,我应该使用双工还是转换流?

1 个答案:

答案 0 :(得分:1)

根据您的问题,我确实认为Transform是您所需要的。在Duplex中,您需要同时实现读写功能,这在您的情况下是不必要的。

代码如下:

const intermediate = measurementStream.pipe(
    new Transform({transform: initialTransforms})
);
intermediate.pipe(someArrayifyStreamToJSON)
intermediate.pipe(
    new Transform({transform: someMoreTransforms})
).pipe(
    new Transform({transform: stringifyToCSV})
).pipe(
    fs.createWriteStream('some_path.csv')
);

我还建议您看一下我创建并支持scramjet的框架。它旨在处理像您这样的情况,并使您的代码更简单:

const {DataStream} = require('scramjet');

// Pass your original stream here, this could be also an 
// AsyncGenerator in node v10 and up.
DataStream.from(measurementStream)
     // you can map with any async or sync operation on the data
    .map(async item => {
         const newData = await doSomeTransforms();
         return newData;
    })
    // tee creates a stream at this point in transforms
    .tee(stream => stream
        .toJSONArray()
        .pipe(fs.createWriteStream('your-intermediate.json'))
    )
    // then you can add some more transforms
    .map(someMapper)
    .filter(someFilter)
    .CSVStringify()
    .pipe(fs.createWriteStream('your-final.csv');

如果您仍然选择第一个路径,那么我建议您使用几个模块,这些模块可以使您的生活更轻松:JSONStreampapaparse都可以在NPM中使用。