8

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

假设我正在运行一个愚蠢的服务器:

$ 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

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

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

4

1 回答 1

7

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

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

你说的是:“将数据从响应传输到标准输出,当标准输出结束时,退出进程。”

你的意思是:“将数据从响应传输到标准输出。响应结束时,退出进程。” 编纂:

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

这里要明确的是,除非您特别关闭process.stdout,否则它永远不会关闭/结束,直到您退出程序。但是,将response在 HTTP 交互完成时结束。

第二种情况类似:

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

你说的:“将数据从标准输入管道传输到请求,当请求结束时,写一条消息。”

你的意思是:“将数据从标准输入传送到请求。当标准输入结束时,写一条消息。” 编纂:

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

这里稍微有点细微差别,因为您可以监听stdinend事件或requestfinish事件:

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

在“服务器”:

$ 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
于 2018-02-25T02:20:54.163 回答