前端使用protobufjs,數據傳輸protobufjs使用記錄
協議緩沖區是一種與語言無關的、與平台無關的、可擴展的序列化結構化數據的方法,用於通信協議、數據存儲等,最初由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;
大概設置:
文中的示例,最終使用的是base64,這樣對ajax請求無影響,直接使用post請求,即可。如果直接用buffer,需要自己封裝ajax;
大概設置:
xhr.responseType = 'blob'
protobuf.js庫很強大,可以繼續研究一下。
同時使用protobuf.js,和后端使用規范版本要一致。
沒有終點,沒有彼岸,堅持就好,願歲月如初