Node.js/Express中的Streaming/Piping JSON.stringify输出

Node.js/Express中的Streaming/Piping JSON.stringify输出,node.js,Node.js,我有一个场景,需要从Node.js/expressrestfulapi返回一个非常大的对象,并将其转换为JSON字符串 res.end(JSON.stringify(obj)); 然而,这似乎不能很好地扩展。具体来说,它在我的测试机器上工作得很好,有1-2个客户端连接,但我怀疑当许多客户端同时请求大型JSON对象时,该操作可能会导致CPU和内存使用量减少 我四处寻找异步JSON库,但似乎有一个问题(特别是,我得到了一个[RangeError])。不仅如此,它还返回一个大数据块中的字符串(例如,

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

res.end(JSON.stringify(obj));
然而,这似乎不能很好地扩展。具体来说,它在我的测试机器上工作得很好,有1-2个客户端连接,但我怀疑当许多客户端同时请求大型JSON对象时,该操作可能会导致CPU和内存使用量减少

我四处寻找异步JSON库,但似乎有一个问题(特别是,我得到了一个[RangeError])。不仅如此,它还返回一个大数据块中的字符串(例如,整个字符串只调用一次回调,这意味着内存占用不会减少)


我真正想要的是JSON.stringify函数的一个完全异步的管道/流版本,这样它可以在将数据直接打包到流中时写入数据。。。这样既节省了内存占用,又避免了以同步方式消耗CPU。

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


但是,如果您试图序列化(字符串化)一个对象,但正在耗尽CPU,那么将该工作拆分为块可能无法真正解决问题。流式传输可能会减少内存占用,但不会减少所需的“工作”总量。

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


您创建了一个流,将对象作为字符串写入到蒸汽中,最后将流传输到res。这可能不会减少总的工作量,但随着时间的推移(通过process.nextTick分离)将其分配,意味着CPU不会被绑定。注意:process.nextTick现在在屈服于事件循环之前执行。使用
setImmediate
。很好,但这不会忽略obj顶层的键名和对象细节吗?
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();
}