客户端 JavaScript 解压缩 Gzip 数据形式 webSocket 时出现问题

Client JavaScript Problem in unzipped Gzip data form webSocket

我有一个通过 WebSocket 向我发送数据的服务,但是数据是 gzip 压缩的。当我尝试解压缩 Blob 数据时遇到问题。我使用了包 fflate gzip-js pako and zlib all with different error but the funny thing when I write the code for node js Server with package node-gzip which underhood used the zlib package mention above everything is fine and the data will be ungzped.

Client.js(问题是 unGzip 数据)

let ws = new WebSocket('wss://api.huobi.pro/ws');

var zlib = require('zlib');;

let zip = {
    gzip: function gzip(input, options) {
        return new Promise(function (resolve, reject) {
            zlib.gzip(input, options, function (error, result) {
                if (!error) resolve(result); else reject(Error(error));
            });
        });
    },
    ungzip: function ungzip(input, options) {
        return new Promise(function (resolve, reject) {
            zlib.gunzip(input, options, function (error, result) {
                if (!error) resolve(result); else reject(Error(error));
            });
        });
    }
};

ws.onopen = ( function () {
    ws.send(`{
                "sub": "market.ethbtc.kline.1min",
                "id": "id1"
            }`);
});

ws.onmessage = async function (event) {
    console.log(await zip.ungzip(event.data));
};

ERROR : Uncaught (in promise) Error: TypeError: Invalid non-string/buffer chunk

Node.js 工作

const {ungzip} = require('node-gzip');

ws = new WebSocket('wss://api.huobi.pro/ws');
    
    ws.on('open', function () {
            ws.send('{
                "sub": "market.ethbtc.kline.1min",
                "id": "id1"
            }');
        });
    
     ws.on('message', function (data) {
            ungzip(data).then((r) => {
                let data = JSON.parse(r.toString());
                console.log(data); 
            }).catch(console.error)
        }); 

在浏览器中,event.data 是 Blob 数据,当我对它们使用 text 方法时,有一些乱码,上面的大多数库和包都说数据头是未知的

但为什么具有相同结构的相同数据点一个在 node.js 上工作,另一个在浏览器中不工作

请帮我解压数据

在上述 Node.js 代码中解压缩后的示例响应数据 我想要我的 Client.js

{
  "ch": "market.ethbtc.kline.1min",
  "ts": 1489474082831, //system update time
  "tick": {
    "id": 1489464480,
    "amount": 0.0,
    "count": 0,
    "open": 7962.62,
    "close": 7962.62,
    "low": 7962.62,
    "high": 7962.62,
    "vol": 0.0
  }
}

无论使用何种模式,这两个例子都有明显的区别。
如果这不起作用(因为它试图立即访问,而不等待承诺):

ws.onmessage = function (event) {
    console.log(gzip.unzip(event.data));
}

只需像在工作版本中一样访问它:

ws.onmessage = function (data) {
    gzip.unzip(data)
    .then((result) => {
        let data = JSON.parse(result.toString());
        console.log(data); 
    })
    .catch(console.error)
}

gzip.unzipungzip 都可能 return 一个承诺。

如果您 console.log event.data 的值,您会发现它实际上是 Blob。您不能直接使用它,而必须转换为 Uint8Array.

我还注意到端点 returns 压缩了 JSON,所以我也会解析它。

我的解决方案:

import { gunzip, strFromU8 } from 'fflate'; 
// If you can't use ES Modules:
// const { gunzip, strFromU8 } = require('fflate');
const ws = new WebSocket('wss://api.huobi.pro/ws');
ws.onopen = function() {
  ws.send(JSON.stringify({
    sub: 'market.ethbtc.kline.1min',
    id: 'id1'
  }));
}
ws.onmessage = function(event) {
  const fr = new FileReader();
  fr.onload = function() {
    gunzip(
      new Uint8Array(fr.result),
      function(err, raw) {
        if (err) {
          console.error(err);
          return;
        }
        const data = JSON.parse(strFromU8(raw));
        // Use the data variable however you wish
      }
    );
  }
  fr.readAsArrayBuffer(event.data);
}