NodeJS流媒体和请求模块

时间:2017-05-14 06:18:23

标签: javascript node.js stream streaming

我有来自网址的以下数据。现在,我想使用任何能够使响应时间最短的方法将数据转换为 新行分隔的JSON 。这是很多数据,因此流媒体对我来说很有意义。

03 Jan 2000,30.00,30.89,29.31,30.89,12487930 ,,,,

2000年1月4日2,32.30,32.35,29.40,30.38,7095350 ,,,,

2000年1月5日,1999.90,30.10,28.00,29.20,5044130 ,,,,

2000年1月6日,19.50,50.34,29.20,29.41,3988780 ,,,,

2000年1月7日,22。20,29.48,27.93,28.50,6264940 ,,,,

我开始使用res.write和res.end的想法。我已经使用了两个axios并请求包用于实验目的!!!

尝试#1状态:成功,TAT:1.25s

function streamPrice(req, res) {
  const { url } = req.query;
  res.set({
        "Cache-Control": "no-store, must-revalidate",
        "Connection": "keep-alive",
        "TRANSFER-ENCODING": "chunked"
    });
    axios(url)
        .then(response => {
            const {
                data
            } = response;
            const rawdata = data.split("\n");
            const opLen = rawdata.length;
            for (let i = opLen -1 ; i >=0 ; i--) {
                const cols = rawdata[i].split(",");
                const elem = {
                    date: parseDateEOD(cols[0]),
                    open: +cols[1],
                    high: +cols[2],
                    low: +cols[3],
                    close: +cols[4],
                    volume: +cols[5],
                    bonus: cols[6],
                    dividend: cols[7],
                    rights: cols[8],
                    split: cols[9],
                    absoluteChange: 0,
                    percentChange: 0
                };             
                res.write(JSON.stringify(elem) + "\n\n");
                res.flush();                       
            }
            res.end(null);
            return;
        })
        .catch(e => {
            logger.info(e);
            return;
        });
}

但我对1.25秒的响应时间不满意,并希望它以毫秒为单位。仅使用请求从url调用数据需要45ms,因此我想将格式化数据转换回< 250-300ms的客户端。有人建议使用滚边提高速度,所以这是我第二次尝试使用滚边

尝试#2状态:成功但没有转型,TAT:250ms

function streamPrice = function(req,res){
const { url } = req.query;
const reqs = request(url);
reqs.pipe(res);
}

现在我想转换每条记录并将其转换为换行符分隔的JSON,所以我写了以下内容:

尝试#3状态:不成功,TAT:250ms

 function streamPrice = function(req,res){
 const { url } = req.query;
    const reqs = request(url,function(error, response, body){
          const rawdata = body.split("\n");
          const opLen = rawdata.length;
          let result;
          for (let i = opLen - 1; i >= 0; i--) {
            const cols = rawdata[i].split(",");
            const elem = JSON.stringify({
              date: parseDateEOD(cols[0]),
              open: +cols[1],
              high: +cols[2],
              low: +cols[3],
              close: +cols[4],
              volume: +cols[5],
              bonus: cols[6],
              dividend: cols[7],
              rights: cols[8],
              split: cols[9],
              absoluteChange: 0,
              percentChange: 0
            }) + "\n\n";
            if(i===0){
              result = elem;
            } else {
              result+=elem;
            }
          } 
          return result;       
      });
    reqs.pipe(res);
    }

但结果数据仍然是未转换的数据集

很少查询: 1.我做错了什么? 2.我应该在管道输出到res之前使用转换流。如果是,您可以帮我解决将块转换为以下 新行分隔的JSON格式的转换流

{"日期":" 2017-05-12T00:00:00.000Z""开":1562,"高" :1562.4,"低":1540.1,"靠近":1548.85"体积":28485"奖金":"& #34;"股息":"""权利":"""分裂":& #34;"" absoluteChange":0," percentChange":0}

{"日期":" 2017-05-11T00:00:00.000Z""开":1572.8,"高" :1580,"低":1555.15"靠近":1561.7,"体积":336193,"奖金":"& #34;"股息":"""权利":"""分裂":& #34;"" absoluteChange":0," percentChange":0}

{"日期":" 2017-05-10T00:00:00.000Z""开":1530.95"高" :1575,"低":1528.55"靠近":1572.8,"体积":74108"奖金":"& #34;"股息":"""权利":"""分裂":& #34;"" absoluteChange":0," percentChange":0}

如有任何进一步的信息,请告诉我

1 个答案:

答案 0 :(得分:1)

您的尝试首先将完整的响应数据拆分为data.split('\n')的行,这意味着必须读取响应两次,一次用于行拆分,一次用于数据点解析。

您应该将响应传递给readline:

const request = require('request');
const readline = require('readline');

function streamPrice = function(req,res){
    const { url } = req.query;

    function transformLine (rawdata) {
        const elem;
        // parse
        res.write(JSON.stringify(elem) + "\n\n");
    }

    request.get(url)
        // response is an instance of http.IncomingMessage, a readable stream
        .on('response', function(response) {
            readline.createInterface({
                input: response
            }).on('line', transformLine);
    });
}

你的个别行不长,所以JSON.stringify应该没问题。

由于您说识别数据集可能比阅读行更复杂,您可以实现自己的转换流:

class ResponseToJSON extends Transform {
  constructor (options) {
    this.cache = '';
    super(options);
  }

  _transform (data, encoding, callback) {
    const chunk = data.toString(encoding);
    // get all yet complete lines
    for (let line of this.splitData(chunk) {
      this.transformLine(line);
    }
    callback();
  }

  splitData (chunk) {
    //prepend the chunk with the cache content
    chunk = this.cache + chunk;
    // apply logic to identify single dataset endings
    // and write result into an array
    const lines = ...
    // the last line may be yet incomplete
    this.cache = lines.pop();
    return lines;
  }

  transformLine (rawData) {
    const elem;
    // parse
    // push out to receiving stream
    this.push(line);
  }

  _flush (callback) {
    // make sure the last line is transformed
    this.transformLine(this.cache);
    callback();
  }
}

function streamPrice = function(req, res){
  const { url } = req.query;

  const transform = new ResponseToJSON();
  transform.pipe(res);

  request.get(url).on('response', function(response) {
    response.pipe(transform);
  }
}

此解决方案可能会减慢一些因素,因为行拆分再次对字符串起作用。如果您看到直接在缓冲区上识别数据集的方法,那肯定会更有效。