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

Zan*_*aes 11 node.js

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

res.end(JSON.stringify(obj));
Run Code Online (Sandbox Code Playgroud)

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

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

我真正想要的是JSON.stringify函数的完全异步管道/流式版本,这样它就可以在数据直接打包到流中时对其进行写入...从而节省了内存占用,同时也消耗了CPU同步时尚.

And*_*rov 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();
} 
Run Code Online (Sandbox Code Playgroud)


Gat*_* VP 5

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

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

  • 注意:process.nextTick现在在屈服于事件循环之前执行.使用`setImmediate`. (2认同)