簡體   English   中英

Stream 大 JSON 來自 REST ZDB9742387JS14CA8DE634A7CE1D083A1Express

[英]Stream large JSON from REST API using NodeJS/ExpressJS

我必須返回一個大的 JSON,這是從 REST ZDB974238714CA8DE634A 服務器 build-8714CA8DE634A 服務器構建到 MongoDB 的結果。 這個 JSON 必須轉換為.csv 以便客戶端可以直接保存生成的 CSV 文件。 我知道最好的解決方案是使用 NodeJS 流和 pipe。 任何人都可以向我建議一個可行的例子嗎? 謝謝。

通常,當想要在 Node 中解析 JSON 時,它相當簡單。 在過去,我會做類似以下的事情。

const fs = require('fs');
const rawdata = fs.readFileSync('file.json');
const data = JSON.parse(rawdata);

或者使用這樣的 require 語句甚至更簡單

const data = require('./file.json');

這兩者都適用於小型甚至中等大小的文件,但是如果您需要解析一個非常大的 JSON 文件,其中一個有數百萬行,將整個文件讀入 memory 不再是一個好選擇。

因此,我需要一種方法來“流式傳輸”JSON 並隨其處理。 有一個名為“stream-json”的不錯的模塊,它完全符合我的要求。

使用stream-json,我們可以使用NodeJS文件stream來處理我們在chucks中的大數據文件。

const StreamArray = require( 'stream-json/streamers/StreamArray');
const fs = require('fs');

const jsonStream = StreamArray.withParser();

//internal Node readable stream option, pipe to stream-json to convert it for us
fs.createReadStream('file.json').pipe(jsonStream.input);

//You'll get json objects here
//Key is the array-index here
jsonStream.on('data', ({key, value}) => {
    console.log(key, value);
});

jsonStream.on('end', ({key, value}) => {
    console.log('All Done');
});

現在我們的數據可以處理而不會用完 memory,但是在我正在處理的用例中,在 stream 內部我有一個異步過程。 正因為如此,我仍然在消耗大量的 memory,因為這只是在 memory 中保留大量未解決的承諾,直到它們完成。

為了解決這個問題,我還必須像這樣使用自定義的可寫 stream。

const StreamArray = require( 'stream-json/streamers/StreamArray');
const {Writable} = require('stream');
const fs = require('fs');

const fileStream = fs.createReadStream('file.json');
const jsonStream = StreamArray.withParser();
const processingStream = new Writable({
    write({key, value}, encoding, callback) {

        //some async operations
        setTimeout(() => {
            console.log(key,value);
            //Runs one at a time, need to use a callback for that part to work
            callback();
        }, 1000);
    },
    //Don't skip this, as we need to operate with objects, not buffers
    objectMode: true
});
//Pipe the streams as follows
fileStream.pipe(jsonStream.input);
jsonStream.pipe(processingStream);
//So we're waiting for the 'finish' event when everything is done.
processingStream.on('finish', () => console.log('All done' ));

可寫 stream 還允許完成每個異步過程並承諾在繼續下一個之前解決,從而避免 memory 備份。

這個堆棧溢出是我獲得這篇文章示例的地方。

在 Nodejs 中解析大型 JSON 文件並獨立處理每個 object另請注意,我在此過程中學到的另一件事是,如果您想以超過默認 RAM 量的方式啟動 Node,您可以使用以下命令。

node --max-old-space-size=4096 file.js

默認情況下,Node.js 中的 memory 限制為 512 mb,要解決此問題,您需要使用命令 –max-old-space-size 增加 memory 限制。 這可用於避免節點內的 memory 限制。 上面的命令將為 Node 提供 4GB 的 RAM 以供使用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM