Потоки/Трубопроводы JSON.stringify вывод в Node.js/Express

У меня есть сценарий, когда мне нужно вернуть очень большой объект, преобразованный в строку JSON, из моего Node.js/Express RESTful API.

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

Однако это, похоже, не очень хорошо масштабируется. В частности, он отлично работает на моей тестовой машине с подключением 1-2 клиентов, но я подозреваю, что эта операция может убивать использование ЦП и памяти, когда многие клиенты запрашивают большие объекты JSON одновременно.

Я искал асинхронную библиотеку JSON, но единственный, что я нашел, кажется, имеет проблему (в частности, я получаю a [RangeError]). Не только это, но и возвращает строку в одном большом фрагменте (например, обратный вызов вызывается один раз со всей строкой, что означает, что размер памяти не уменьшается).

То, что я действительно хочу, это полностью асинхронная потоковая версия функции JSON.stringify, так что она записывает данные, поскольку они упакованы непосредственно в поток... таким образом, сохраняя меня как объем памяти, так и от потребления CPU синхронно.

Ответ 1

В идеале вы должны передавать свои данные по своему усмотрению, а не буферизировать все в один большой объект. Если вы не можете изменить это, вам нужно сломать строку на более мелкие единицы и разрешить основной цикл событий обрабатывать другие события, используя 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();
} 

Ответ 2

Похоже, вы хотите Dominic Tarr JSONStream. Очевидно, что для слияния с куском требуется сборка.

Однако, если вы максимизируете процессор, пытающийся сериализовать (Stringify) объект, то разделение этой работы на куски может не решить эту проблему. Потоковая передача может уменьшить объем памяти, но не уменьшит общий объем работы.