Лучший способ получить информацию из порожденного дочернего процесса

У меня странная проблема.

Я должен создать процесс в своем приложении node (внешний, разветвление невозможно). затем этот дочерний процесс отправляет вывод, который мне нужно вернуть и сохранить в БД. То, как я это делаю сейчас, заключается в том, чтобы повторять каждую строку моих данных (это JSON) и слушать, что приходит на стандартный вывод.

дочерний код:

var cntSent=0
for (var j = 0, lUF = uniqueFlyers.length; j < lUF; j++) {
  var products = uniqueFlyers[j].products;
  for (var k = 0, lP = products.length; k < lP; k++) {
    var pstr = products[k].product;
    this.echo(pstr);
    cntSent+=1;
  }
}
console.log(cntSent);

в конце cntSent=10000.

Сторона узла:

var cntReceived
proc.stdout.on('data', function(line) {
  cntReceived+=1;
  console.log(line);
});
proc.on('close', function (code) {
  console.log(cntReceived);
});

в конце cntReceived = 3510.

Я вижу все свои выведенные данные, но они агрегируются и поступают большими кусками. Моя идея состоит в том, чтобы записать файл, а затем обработать файл с помощью узла, но это кажется избыточным, и я хотел бы начать обработку данных по мере их поступления. Любые предложения относительно наиболее точного и быстрого способа?

РЕДАКТИРОВАТЬ: как обычно, запись вопросов заставила меня задуматься. Я просто глуп, и было бы лучше буферизовать данные, а затем анализировать их? Это JSON, черт возьми!


person xShirase    schedule 15.11.2013    source источник


Ответы (2)


Нет необходимости записывать данные в файл, а затем обрабатывать файл; вам также не нужно буферизовать все данные перед их обработкой.

Если данные, которые вы выводите, находятся в формате JSON, я бы предложил использовать JSONStream в родительском коде. Это позволит вам анализировать вывод на лету. Ниже приведен пример.

Дочерний код выведет массив JSON:

// Child code
console.log('['); // We'll output a JSON array
for (var j = 0, lUF = uniqueFlyers.length; j < lUF; j++) {
  var products = uniqueFlyers[j].products;
  for (var k = 0, lP = products.length; k < lP; k++) {
    var pstr = products[k].product;
    console.log(JSON.stringify(pstr)); // output some JSON
    if ((j !== lUF - 1) && (k !== lP - 1))
        console.log(','); // output commas between JSON objects in the array
    cntSent+=1;
  }
}
console.log(']'); // close the array

В то время как родительский код будет читать этот массив JSON и обрабатывать его. Мы используем селектор * для выбора всех элементов массива. Затем JSONStream будет выдавать каждый документ JSON один за другим по мере их анализа. Получив эти данные, мы можем использовать поток с возможностью записи, который будет читать JSON. объекты, а затем что-то (что-нибудь!) с ними делать.

// Parent code
var stream = require('stream');
var jsonstream = require('JSONStream').parse('*');
var finalstream = new stream.Writable({ objectMode: true }); // this stream receives objects, not raw buffers or strings
finalstream._write = function (doc, encoding, done) {
    console.log(doc);
    done();
};

proc.stdout.pipe(jsonstream).pipe(finalstream);
person Paul Mougel    schedule 15.11.2013
comment
Звучит здорово, но не все мои выходные данные представлены в формате JSON. Могу ли я добавить условие для отправки данных в поток, только если data.indexOf('[')===1? - person xShirase; 16.11.2013
comment
Не без усложнения кода. Как будут выглядеть данные в другом случае? Разве нельзя преобразовать его в массив JSON? - person Paul Mougel; 16.11.2013
comment
Есть несколько сообщений, которые выглядят как «Запись БД: номер записи». Я полагаю, что мог бы JSONify, но мне все равно нужно было бы как-то отделить их от остальных. - person xShirase; 16.11.2013
comment
Я бы посоветовал либо JSONify их, либо выводить эти специальные сообщения в другой поток, например proc.stderr. - person Paul Mougel; 16.11.2013
comment
Неплохая идея! Если я JSONify, как мне отделить сообщения от тех, которые я хочу? В финальном стриме._write? - person xShirase; 16.11.2013
comment
Действительно, в finalstream._write вы бы сделали некоторую проверку типа сообщения. - person Paul Mougel; 16.11.2013

var cntReceived
proc.stdout.on('data', function(line) {
  var arr = data.split('\n');
  cnt+=arr.length-1;
  console.log(line);
});
proc.on('close', function (code) {
  console.log(cntReceived);
});

Выход: cntReceived = 10000

person xShirase    schedule 15.11.2013