2016-01-24 2 views
1

Я порождаю ребенка, который производит много данных (я использую здесь 'ls -lR /' здесь в качестве примера). Я хочу асинхронно читать stdout ребенка по 100 байт за раз.node.js - чтение дочернего процесса stdout 100 байт за один раз

Так что я хочу сделать: get100(), а затем (process100) .then (get100) .then (process100) .then (...

По какой-то причине этот код только петли. 3 раза и я перестану получать читаемым события. Я не могу понять, почему?

var Promise = require('bluebird'); 
var spawn = require("child_process").spawn; 

var exec = spawn("ls", [ "-lR", "/"]); 

var get100 = function() { 
    return new Promise(function(resolve, reject) { 
     var tryTransfer = function() { 
      var block = exec.stdout.read(100); 
      if (block) { 
      console.log("Got 100 Bytes"); 
      exec.stdout.removeAllListeners('readable'); 
      resolve(); 
      } else console.log("Read Failed - not enough bytes?"); 
     }; 
     exec.stdout.on('readable', tryTransfer); 
    }); 
}; 

var forEver = Promise.method(function(action) { 
    return action().then(forEver.bind(null, action)); 
}); 

forEver(
    function() { return get100(); } 
) 
+0

Это, по-видимому, очень запутанный способ сделать простой 'ls'. Что вы пытаетесь сделать? Что вы делаете со 100 байтами, которые вы читаете? – Shanoor

+0

Я на самом деле не работает. Я запускаю запатентованный .exe, который генерирует тонну данных. У меня есть список потребителей. Мне нужно получить первые 100 байт, добавить заголовок и отправить его первому пользователю, следующий 100 + заголовок для второго потребителя и т. Д. Я пытаюсь сделать это асинхронно. – GroovyDotCom

+0

Я вижу, поскольку exec.stdout - это поток, вы можете придерживаться потоков. Я пишу anwser. – Shanoor

ответ

2

Использование event-stream, вы можете испускают данные 100 байт из порожденного процесса до тех пор, пока данные для чтения (потоки async):

var es = require('event-stream'); 
var spawn = require("child_process").spawn; 

var exec = spawn("ls", ["-lR", "/"]); 

var stream = es.readable(function (count, next) { 
    // read 100 bytes 
    while (block = exec.stdout.read(100)) { 
     // if you have tons of data, it's not a good idea to log here 
     // console.log("Got 100 Bytes"); 
     // emit the block 
     this.emit('data', block.toString()); // block is a buffer (bytes array), you may need toString() or not 
    } 

    // no more data left to read 
    this.emit('end'); 
    next(); 
}).on('data', function(data) { 
    // data is the 100 bytes block, do what you want here 

    // the stream is pausable and resumable at will 
    stream.pause(); 
    doStuff(data, function() { 
     stream.resume(); 
    }); 
}); 
+0

Если я это правильно понимаю, поток будет считаться как можно быстрее и будет переведен на вызовы doStuff (данные). Итак, если doStuff не поддерживает, не закончится ли процесс в конечном итоге? – GroovyDotCom

+0

Пробовал запустить этот код как есть. doStuff никогда не называется? – GroovyDotCom

+0

@GroovyDotCom, да, он работает как можно быстрее, но при необходимости вы можете приостановить входной поток (я редактирую ответ, чтобы добавить пример). 'doStuff()' никогда не звонил? Это странно, я пробовал с помощью простой console.log, и я получаю длинный вывод из 'ls', разбитый на 100 байт: https://tonicdev.com/shanshan/streamed-stdout – Shanoor

Смежные вопросы