node.js: Как обнаружить пустой поток стандартного ввода? - PullRequest
18 голосов
/ 10 февраля 2012

У меня есть скрипт / сервер node.js, который читает некоторые входные данные из stdin при его запуске. Однако иногда нет данных для передачи. Это хлопотно, потому что кажется, что в этом случае не вызываются события data или end. Как я могу определить, когда это происходит в коде node.js?

Я бы хотел избежать необходимости добавлять специальные «конечные» символы в конце ввода, чтобы не причинять неудобства клиенту. Связанный код ниже:

  var newHTML = '';
  var gfm = spawn(__dirname + '/node_modules/docter/bin/github-flavored-markdown.rb');
  process.stdin.on('data', function(chunk){
    gfm.stdin.write(chunk);
  });
  process.stdin.on('end', function(){
    gfm.stdin.end();
  });
  gfm.stdout.on('data', function(data) {
    newHTML += data;
  });
  gfm.on('exit',function(ecode){
    socket.emit('newContent', newHTML);
  });
  process.stdin.resume();

Ответы [ 4 ]

5 голосов
/ 04 февраля 2014

Я верю, что может случиться так, что вы вообще не даете пара stdin.

Пример Øystein Steimler показывает, что вы вводите / dev / null в свое приложение:

узел pipe.js </ dev / null </p>

Однако никогда не обращайтесь, когда вы вообще не транслируете stdin в приложение. Просто запуск node pipe.js не завершится, потому что он все еще ждет stdin .

Вы можете проверить это самостоятельно с другими программами Unix, например cat

Попробуйте запустить это:

cat < /dev/null

Теперь попробуйте просто запустить:

cat

Он не выходит, потому что он ожидает стандартного ввода. Вы можете ввести в терминал и отправить в программу, нажав клавишу ввода. Он по-прежнему не будет выходить (и ждать большего ввода), пока не получит EOF , который вы можете сделать с помощью ctrl + d

5 голосов
/ 23 октября 2013

Событие end из process.stdin.

обнаруживает пустой или отсутствующий поток STDIN. Этот простой скрипт stdin.js демонстрирует, что:

process.stdin.on( 'data', function(data) { console.log( data ) } );
process.stdin.on( 'end', function() { console.log( 'EOF' ) } );

Различные сценарии:

$ echo test | node stdin.js
<Buffer 74 65 73 74 0a>
EOF
$ echo -n | node stdin.js
EOF
$ node stdin.js < /dev/null
EOF
$

Этот скрипт pipe.js демонстрирует, что использование канала для порожденного дочернего процесса работает очень хорошо:

var spawn = require('child_process').spawn;
var cat = spawn( '/bin/cat' );
cat.stdout.on( 'data', function(data) { console.log( data ) } );
cat.stdout.on( 'end', function() { console.log( 'EOF' ) } );

process.stdin.pipe(cat.stdin);

Как и ожидалось:

$ echo test | node pipe.js
<Buffer 74 65 73 74 0a>
EOF
$ echo -n | node pipe.js
EOF
$ node pipe.js < /dev/null
EOF
$
2 голосов
/ 24 февраля 2015

Что вы можете сделать, это заставить ваше приложение принять аргумент, подобный -s, который делает его читаемым из стандартного ввода.

Это то, что делает инструмент CLI LiveScript:

-s, --stdin read stdin

1 голос
/ 17 ноября 2018

Способ stdin работает, то, что вы хотите, напрямую невозможно.

Как уже отмечали другие, событие end никогда не сработает без чего-то вроде < /dev/null, чтобы сгенерировать это EOF . В противном случае программа ожидает, пока терминал отправит ^D.

Альтернативный подход, который может работать для вас, - установить тайм-аут, который истекает через короткое время, если на stdin нет активности. Это не идеально, но работает:

function handleData(chunk) {
  //clearTimeout(timeout);
  gfm.stdin.write(chunk);
}
function handleEnd() {
  //clearTimeout(timeout);
  gfm.stdin.end();
}
function handleTimeout() {
  process.stdin.removeListener('data', handleData);
  process.stdin.removeListener('end', handleEnd);

  // Do whatever special handling is needed here.
  gfm.stdin.end();
}

const timeoutMilliseconds = 100;

process.stdin.on('data', handleData);
process.stdin.on('end', handleEnd);
const timeout = setTimeout(handleTimeout, timeoutMilliseconds);

// You could skip the rest of this code if you just add `clearTimeout(timeout)`
// to the body of `handleData` and `handleEnd` but that would call `clearTimeout` excessively.
function stopTimeout() {
  process.stdin.removeListener('data', stopTimeout)
  process.stdin.removeListener('end', stopTimeout);
  clearTimeout(timeout);
}

process.stdin.on('data', stopTimeout);
process.stdin.on('end', stopTimeout);
...