简体   繁体   English

Node.js HTTP 响应流

[英]Node.js HTTP response streams

Using the native http.get() in Node.js, I'm trying to pipe a HTTP response to a stream that I can bind data and end events to.在 Node.js 中使用本机http.get() ,我试图将 HTTP 响应通过管道传输到我可以将dataend事件绑定到的流。

I'm currently handling this for gzip data, using:我目前正在处理 gzip 数据,使用:

http.get(url, function(res) {
  if (res.headers['content-encoding'] == 'gzip') {
    res.pipe(gunzip);
    gunzip.on('data', dataCallback);
    gunzip.on('end', endCallback);
  }
});

Gunzip is a stream and this just works. Gunzip 是一个流,这只是有效。 I've tried to create streams (write streams, then read streams) and pipe the response, but haven't been having much luck.我尝试创建流(写入流,然后读取流)并通过管道传输响应,但运气不佳。 Any suggestions to replicate this same deal, for non-gzipped content?对于非 gzip 压缩的内容,是否有任何建议可以复制相同的交易?

The response object from a HTTP request is an instance of readable stream. HTTP 请求的响应对象是可读流的实例。 Therefore, you would collect the data with the data event, then use it when the end event fires.因此,您将使用data事件收集数据,然后在end事件触发时使用它。

var http = require('http');
var body = '';

http.get(url, function(res) {
  res.on('data', function(chunk) {
    body += chunk;
  });
  res.on('end', function() {
    // all data has been downloaded
  });
});

The readable.pipe(dest) would basically do the same thing, if body in the example above were a writable stream.如果上面例子中的body是一个可写的流,那么readable.pipe(dest)基本上会做同样的事情。

Nowadays the recommended way of piping is using the pipeline function.现在推荐的配管方式是使用管道功能。 It is supposed to protect you from memory leaks.它应该可以保护您免受内存泄漏。

const { createReadStream} = require('fs');
const { pipeline } = require('stream')
const { createServer, get } = require('http')

const errorHandler = (err) => err && console.log(err.message);

const server = createServer((_, response) => {
  pipeline(createReadStream(__filename), response, errorHandler)
  response.writeHead(200);
}).listen(8080);

get('http://localhost:8080', (response) => {
  pipeline(response, process.stdout, errorHandler);
  response.on('close', () => server.close())
});

Another way of doing it that has more control would be to use async iterator另一种具有更多控制权的方法是使用异步迭代器

async function handler(response){
  let body = ''
  for await (const chunk of response) {
    let text = chunk.toString()
    console.log(text)
    body += text
  }
  console.log(body.length)
  server.close()
}

get('http://localhost:8080', (response) => handler(response).catch(console.warn));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM