在Node.js / Express中流式传输/管道JSON.stringify输出

时间:2012-11-21 23:40:52

标签: node.js

我有一个场景,我需要从Node.js / Express RESTful API返回一个非常大的对象,转换为JSON字符串。

res.end(JSON.stringify(obj));

但是,这似乎不能很好地扩展。具体来说,它在我的测试机器上运行良好,有1-2个客户端连接,但我怀疑这个操作可能会杀死CPU和许多客户端同时请求大型JSON对象时的内存使用情况。

我一直在寻找异步JSON库,但是the only one I found似乎有问题(具体来说,我得到了[RangeError])。不仅如此,它还会在一个大块中返回字符串(例如,使用整个字符串调用一次回调,这意味着内存占用不会减少)。

我真正想要的是JSON.stringify函数的完全异步管道/流式版本,这样它就可以直接打包到数据流中来编写数据......从而节省了内存占用空间,也消耗了内存CPU以同步方式。

2 个答案:

答案 0 :(得分:10)

理想情况下,您应该按原样流式传输数据,而不是将所有数据缓冲到一个大型对象中。如果你不能改变它,那么你需要将stringify分解为更小的单位并允许主事件循环使用setImmediate处理其他事件。示例代码(我假设主对象具有许多顶级属性并使用它们来分割工作):

function sendObject(obj, stream) {
    var keys = Object.keys(obj);
    function sendSubObj() {
       setImmediate(function(){
          var key = keys.shift();
          stream.write('"' + key + '":' + JSON.stringify(obj[key]));
          if (keys.length > 0) {
            stream.write(',');
            sendSubObj();
          } else {
            stream.write('}');
          }
       });
    })
    stream.write('{');
    sendSubObj();
} 

答案 1 :(得分:5)

听起来你想要Dominic Tarr的JSONStream。显然,需要一些程序集将它与express合并。

但是,如果您最大限度地尝试序列化( Stringify )对象的CPU,那么将该工作拆分为块可能无法真正解决问题。流式传输可能会减少内存占用,但不会减少所需的“工作量”。