node.js - 解析管道响应有时会得到分块数据

标签 node.js stream request pipe response

我有一个用于调用服务的nodejs代理。在响应中,请求通过管道传输到服务 url(我想如果您想在返回响应之前解析响应,那么这是正确的方法)。问题是解析器有时会在 JSON.parse(data) 上失败,因为它出现意外的输入结束。从我在调试时看到的问题来看,正在解析的数据不完整(即使服务正确返回它)。 我对管道和流没有太多经验,所以我不确定为什么有时会失败。

//Request setup
            r.on('response', function(resp) {
            if (resp.statusCode === 200) {
                r.pipe(responseParser(config.get('service:url'))).pipe(res);
            } else {
                r.pipe(res);
            }
        });

//Parser module
    var _ = require('lodash'),
        stream = require('stream');

    module.exports = function responseParser(url) {
        var data = '',
            parser = new stream.Transform({
                objectMode: true
            });

        parser._transform = function (chunk, encoding, done) {
            data += chunk.toString();
            done();
        };

        parser._flush = function (done) {
            if (data) {
                var obj = mapValues(JSON.parse(data));
                    this.push(JSON.stringify(obj));
            }

            done();
        };

        function mapValues(data){
            ...
        }

        return parser;
    }   

我仍然不知道为什么有时在返回所有数据 block 之前会调用刷新,但为了避免这种情况,我所做的只是在 block 到达时对其进行解析,通过确保在 block 中我不会获得有关我需要映射的值的部分数据。如果一个 block 仅包含目标值的部分信息,我会将其删除,并将其添加到下一个 block 的开头。这样,数据在传入时就被解析,因此我不必依赖仅在所有数据返回时才调用刷新的事实。

最佳答案

我会禁用objectMode,因为在这种情况下没有必要。此外,您还需要将 JSON 解析包装在 try-catch 中,以防出现格式错误的输入:

module.exports = function responseParser(url) {
  var data = '';
  var parser = new stream.Transform();
  parser._transform = function(chunk, encoding, done) {
    data += chunk;
    done();
  };
  parser._flush = function(done) {
    var err;
    if (data) {
      try {
        var obj = mapValues(JSON.parse(data));
        this.push(JSON.stringify(obj));
        this.push(null);
      } catch (ex) {
        err = ex;
      }
    }
    done(err);
  };

  function mapValues(data){
    // ...
  }

  return parser;
};

您可能还需要先检查 resp.headers['content-type'] 是否包含 application/json,然后再尝试解析它,并且您可能希望创建一个自定义 Transform 子类并实例化它,而不是每次都创建新的 _transform()_flush() 函数。

关于node.js - 解析管道响应有时会得到分块数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36308552/

相关文章:

http - 如何将 io.ReadCloser 流式传输到 http.ResponseWriter

javascript - AngularJS - $http.get 请求被取消

node.js - 一次修改一个文件

javascript - 在 Javascript 中递归遍历树

javascript - Node js/Mongoose .find()

node.js - 在 Log4js 中禁用控制台打印

C++在不使用字符串流的情况下读取具有任意长度和格式的行的多行文件

java - try-with-resource资源创建的执行顺序

python - 使用 urllib、urllib2 和 request 避免类似 "Pyramid of Doom"的语法

python - 如何从 Python 请求/Beautiful Soup 中的某些文本参数获取特定的 HTML 行