前端小工具:protobufjs數據傳輸


前端使用protobufjs,數據傳輸protobufjs使用記錄

protobuf.js

協議緩沖區是一種與語言無關的、與平台無關的、可擴展的序列化結構化數據的方法,用於通信協議、數據存儲等,最初由Google設計(請參閱)。

 

協議.js是一個純JavaScript實現,支持節點.js和瀏覽器。它易於使用,速度極快,並且可以與.proto文件一起開箱即用

1, 安裝protobufjs

npm install protobufjs [--save --save-prefix=~]

2.使用

// const protobufjs = require('protobufjs')
import protobufjs from 'protobufjs'


// 要用到load模塊
  const { load } = protobufjs

實例:

export default class protobuf {
    static exportBuffer(parsedJsonList, molecule, proto , taskitem){
        return new Promise((resolve, reject) => {
            load(proto, (err, root) => {
              if (err) {
                console.log(err)
                return reject(new Error('proto文件加載出錯!'));
              }
              let prototxts = []
              parsedJsonList.forEach(parsedJson => {
                let parsedMessage = root.lookupType('TIV.' + parsedJson.header.type + 'Def')
                const single = parsedMessage.create(parsedJson)
                const singleBuffer = parsedMessage.encode(single).finish() // 這個singleBuffer發給后台就好
                prototxts.push({
                  msgId: parsedJson.id,
                  msgType: parsedJson.header.type,
                  msgContent: singleBuffer,
                  taskType: parsedJson.taskType,
                  isEntry: isEntry(parsedJson.header.type, parsedJson.id, molecule)
                })
              })
      
              let prototxtsMessage = root.lookupType('TIV.AllOperatorPb')
              const all = prototxtsMessage.create({
                allOperatorPb: prototxts,
                taskFlow: taskitem ? taskitem : ''
              })
              const allBuffer = prototxtsMessage.encode(all).finish() // 這個buffer發給后台就好
              const b64 = btoa(String.fromCharCode.apply(null, allBuffer))
            //   this.analysisBuffer(b64, proto)
              resolve(b64);
            })
        })
    }
    static analysisBuffer(b64, proto) {
        let allBuffer = atob(b64).split('').map(function (c) { return c.charCodeAt(0) })
        return new Promise((resolve, reject) => {
            load(proto, (err, root) => {
                if (err) {
                    reject(err)
                    return console.log('proto文件加載出錯');
                }
                let prototxtsMessage = root.lookupType('TIV.AllOperatorPb')
                const alldata = prototxtsMessage.decode(allBuffer)
                alldata.allOperatorPb.map(item => {
                    let parsMessage = root.lookupType('TIV.' + item.msgType + 'Def')
                    const fields = [];
                    if (Object.keys(parsMessage.Parameter.fields).length > 0) {
                        Object.keys(parsMessage.Parameter.fields).forEach(ikey => {
                            let value = 0;
                            if (parsMessage.Parameter.fields[ikey].type === "bool") {
                                value = false;
                            }
                            fields.push({
                                title: ikey,
                                value: parsMessage.Parameter.fields[ikey].typeDefault || value
                            })
                        })
                    }
                    const prototxt = parsMessage.decode(item.msgContent)
                    fields.forEach(field => {
                        if(prototxt['param']){
                            prototxt['param'][field.title] = prototxt['param'][field.title] ? prototxt['param'][field.title] : field.value;
                        }  
                    })
                    prototxt.header.type = prototxt.header.type.split('Operator')[0]
                    item.msgContent = formatInit(prototxt)
                })
                if(process.env.NODE_ENV === 'development'){
                    console.log('解析后json數據:',alldata.allOperatorPb)
                }
                resolve(alldata.allOperatorPb);
            })
        })
    }
}
protobufjs使用,數據的轉換依賴 proto配置文件,protobufjs默認支持本地同源文件請求,如果proto文件是固定的不需要更改的,配置在前端靜態文件就好了;如何會動態變更的話,需要用到絕對路徑,需要解決跨域問題;

修改protobufjs對象原型默認的load請求文件方式:

protobufjs.util.fetch.xhr = function fetch_xhr(filename, options, callback) {
    var xhr = new XMLHttpRequest();
    xhr.onreadystatechange /* works everywhere */ = function fetchOnReadyStateChange() {

        if (xhr.readyState !== 4)
            return undefined;

        // local cors security errors return status 0 / empty string, too. afaik this cannot be
        // reliably distinguished from an actually empty file for security reasons. feel free
        // to send a pull request if you are aware of a solution.
        if (xhr.status !== 0 && xhr.status !== 200)
            return callback(Error("status " + xhr.status));

        // if binary data is expected, make sure that some sort of array is returned, even if
        // ArrayBuffers are not supported. the binary string fallback, however, is unsafe.
        if (options.binary) {
            var buffer = xhr.response;
            if (!buffer) {
                buffer = [];
                for (var i = 0; i < xhr.responseText.length; ++i)
                    buffer.push(xhr.responseText.charCodeAt(i) & 255);
            }
            return callback(null, typeof Uint8Array !== "undefined" ? new Uint8Array(buffer) : buffer);
        }
        return callback(null, xhr.responseText);
    };

    if (options.binary) {
        // ref: https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Sending_and_Receiving_Binary_Data#Receiving_binary_data_in_older_browsers
        if ("overrideMimeType" in xhr)
            xhr.overrideMimeType("text/plain; charset=x-user-defined");
        xhr.responseType = "arraybuffer";
    }

    xhr.open("GET", filename);
    let headers = options.headers || {};

    if (process.env.NODE_ENV !== 'development') {
        headers['X-TC-Action'] = 'WorkbenchPb'
        headers['X-TC-Region'] = 'ap-guangzhou'
        headers['X-TC-Timestamp'] = Math.round(new Date().getTime()/1000).toString()
        headers['X-TC-Service'] = 'AMTPGate'
        headers['X-TC-Version'] = '2020-05-14'
    }

    for (let item in headers) {
        if (headers.hasOwnProperty(item) && headers[item] !== null) {
            xhr.setRequestHeader(item, headers[item]);
        }
    }
    xhr.send();
};
Buffer數據流,傳輸速度非常快,數據保密性更強,前后端數據傳輸跟健壯。
文中的示例,最終使用的是base64,這樣對ajax請求無影響,直接使用post請求,即可。如果直接用buffer,需要自己封裝ajax;
大概設置:
xhr.responseType = 'blob'

 

protobuf.js庫很強大,可以繼續研究一下。

同時使用protobuf.js,和后端使用規范版本要一致。

 

沒有終點,沒有彼岸,堅持就好,願歲月如初


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM