如何在 Node 中关闭标准输入?

How do I close stdin in Node?

我正在学习 Node.js 并认为我有一个非常简单的脚本,但任何调整都不会使我的脚本永远挂起。

假设我有一个哑服务器 运行ning:

$ nc -l 32001 <<EOF
HTTP/1.1 200 OK
Content-Type: text/plain

Works
EOF

我运行以下脚本:

var http = require('http');
var options = {
  hostname: 'localhost',
  port: 32001,
  method: 'POST',
  headers: {'Content-Type': 'text/plain'}
};
var req = http.request(options, res => {
  var exitCode = res.statusCode >= 200 && res.statusCode < 300 ? 0 : 1;
  res.pipe(process.stdout).on('end', () => process.exit(exitCode));
});
req.on('error', error => console.error(error));
process.stdin.pipe(req)
  .on('end', () => console.log('this does trigger'));

但是当我执行以下操作时:

$ echo foobar | node my-script.js

它只是挂起,永远不会到达请求回调。我希望请求流结束并调用 http.request 回调,然后输出 Works 并最终退出进程。

我检查过 end 事件确实是从 process.stdin.pipe() 调用的,并且我试图在 end 回调中手动结束 req 流。但它不会结束。如何将标准输入通过管道传输到 http.request 并仍然让它结束流?

你走在正确的轨道上;您只需要将您的侦听器附加到适当的对象事件。在第一种情况下(书面的,而不是执行的):

res.pipe(process.stdout).on('end', () => process.exit(exitCode));

你说的:"Pipe the data from response to stdout, and when stdout ends, exit the process."

你的意思:"Pipe the data from response to stdout. When response ends, exit the process." 编码:

res.pipe(process.stdout);
res.on('end', () => process.exit(exitCode));

这里需要明确的一点是,除非您明确关闭 process.stdout,否则它将 永远不会 close/end 直到您退出该程序。然而,response 将在 HTTP 交互完成时结束。

第二种情况类似:

process.stdin.pipe(req)
  .on('end', () => console.log('this does trigger'));

你说的:"Pipe the data from stdin to request, and when request ends, write a message."

你的意思:"Pipe the data from stdin to request. When stdin ends, write a message." 编码:

process.stdin.pipe(req);
process.stdin.on('end', () => console.log('this does trigger'));

这里稍微有些细微差别,因为您可以监听 stdinend 事件或 request 的事件finish 事件:

process.stdin.pipe(req).on('finish', () => console.log('Request has finished writing/sending');
process.stdin.on('end', () => console.log('Stdin has no more data'));

那么,为了完整起见,您的工作客户会回复您,为了假设的教学清晰度,对文本进行了一些轻微的修改:

var http = require('http');
var options = {
  hostname: 'localhost',
  port: 32001,
  method: 'POST',
  headers: {'Content-Type': 'text/plain'}
};
var req = http.request(options, res => {
  var exitCode = res.statusCode >= 200 && res.statusCode < 300 ? 0 : 1;
  res.pipe(process.stdout);
  res.on('end', () => {
    console.log('Response (IncomingMessage) has no more data; exiting with code:', exitCode);
    process.exit(exitCode);
  });
});
req.on('error', error => console.error(error));
process.stdin.on('end', () => console.log('Stdin has no more data.'));
process.stdin.pipe(req).on('finish', () => console.log('Request has finished writing/sending'));

命令行输出:

$ echo Some text from stdin | node test.js; echo $?
Stdin has no more data.
Request has finished writing/sending
Works
Response (IncomingMessage) has no more data; exiting with code: 0
0

在 "the server":

$ nc -l 32001 <<EOF
HTTP/1.1 200 OK
Content-Type: text/plain

Works
EOF
POST / HTTP/1.1
Content-Type: text/plain
Host: localhost:32001
Connection: close
Transfer-Encoding: chunked

15
Some text from stdin

0