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/

相关文章:

ios - AFnetworking 不断返回响应代码=-1011“请求失败 : client error (422)

c# - 获取用户在浏览器中输入的确切网址

asynchronous - 如何在 go lang 中进行非阻塞的 http 请求?

node.js - 如何在 Windows 中安装 Nodist 时设置 PATH

php - 如何在请求之间保留 MongoDB 游标?

node.js - 如何从 .wav 文件转录完整的音频文本?

java - 尝试将对象实例写入 ObjectOutputStream 时出现 NullPointerException

c++ - 使用标准 C++/C++11、14、17/C 检查文件是否存在的最快方法?

javascript - 当人们说用 javascript 构建堆栈或完整堆栈时,他们的意思是什么?它与 Node JS 有何关系?

iOS:如何检查流连接是否超时