node.js:如何检测空的stdin流?

Sua*_*uan 18 stdin detect node.js

我有一个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();
Run Code Online (Sandbox Code Playgroud)

Øys*_*ler 5

end事件检测到空的或没有STDIN流process.stdin.

这个简单的脚本stdin.js演示了:

process.stdin.on( 'data', function(data) { console.log( data ) } );
process.stdin.on( 'end', function() { console.log( 'EOF' ) } );
Run Code Online (Sandbox Code Playgroud)

不同场景:

$ echo test | node stdin.js
<Buffer 74 65 73 74 0a>
EOF
$ echo -n | node stdin.js
EOF
$ node stdin.js < /dev/null
EOF
$
Run Code Online (Sandbox Code Playgroud)

此脚本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);
Run Code Online (Sandbox Code Playgroud)

正如所料:

$ echo test | node pipe.js
<Buffer 74 65 73 74 0a>
EOF
$ echo -n | node pipe.js
EOF
$ node pipe.js < /dev/null
EOF
$
Run Code Online (Sandbox Code Playgroud)


JD *_*cks 5

我相信可能发生的事情是,你根本没有给出斯坦丁的动力.

ØysteinSteimler的例子显示你将/ dev/null输入你的应用程序:

node pipe.js </ dev/null

但是,当您根本不将stdin流式传输到应用程序时,永远不会解决.刚刚运行node pipe.js不会退出,因为它仍在等待stdin.

例如,您可以使用其他unix程序自行测试 cat

试试这个:

cat < /dev/null
Run Code Online (Sandbox Code Playgroud)

现在尝试运行:

cat
Run Code Online (Sandbox Code Playgroud)

它不会退出,因为它正在等待stdin.您可以输入终端并按Enter键发送到程序.它仍然不会退出(并等待更多输入),直到它收到你可以用+ 做的EOFctrld

  • 我怎样才能发现这种情况何时发生?我没有收到任何`readline``close`或`process.stdin``end`事件. (2认同)

rai*_*ine 5

您可以做的就是让您的应用程序接受一个参数,例如-s使其从标准输入读取。

这就是 LiveScript 的 CLI 工具的作用:

-s, --stdin read stdin


Cam*_*ind 5

方法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);
Run Code Online (Sandbox Code Playgroud)