微信小程序使用pako.js的踩坑筆記


問題

  今天組長跟我們討論了個問題,說是文章存儲占用有點大,消耗寬帶流量費,讓我看看能不能找個方法解決一下(文章存儲的是html字符串)。第一反應是沒什么頭緒,能想到的就是將相同的字符串替換成一個標識之類的,小程序再通過標識替換回原本的字符(感覺就不是很靠譜...)。

  后來發現真的不靠譜,首先每篇文章樣式可能都不一樣,需要很多對應的字典,即使是這樣大概預估了下,也減少不過10多k左右。唉,還是面向百度編程吧,看看有沒有什么別人寫好的模塊可以用一下。

  然后就找到了pako.js,具體實現是本地gzip壓縮成base64。我在pc端稍微測試了下,原本150k左右的文章,能夠壓縮到14k,壓縮率90%。嗯,不錯,開始搞一下。可后面的路並沒有我想的那么順暢...

准備工作

  要是用第三方模塊,肯定需要npm包管理工具是吧。npm init,然后npm i pako,一頓操作,引入文件測試。哦豁,報錯找不到這個包。因為在公司一直都是用的原生小程序語法開發,沒使用過三方模塊,所以這方面一直沒去了解,還以為和web端的差不多。沒事嘛,面向百度編程。百度了一堆亂七八糟的,都沒什么作用,還是乖乖的看官方文檔吧,沒想到幾分鍾的事就解決了(有時候還是文檔靠譜)。

  1. npm init  創建package.json
  2. npm i pako
  3. 開發者工具左上角 -> 工具 -> 構建npm
  4. 開發者工具右上角 -> 勾選使用npm模塊
  5. 文件中引入模塊使用

  附上文檔鏈接:https://developers.weixin.qq.com/miniprogram/dev/devtools/npm.html

開始踩坑

   數據庫存儲的文章已經壓縮過,現在要做的就是在小程序解壓縮還原成html字符串並渲染出來。

  壓縮文章代碼:

1 function zip(str){ 2       let binaryString = pako.gzip(encodeURIComponent(str), { to: 'string' }), 3           res = btoa(binaryString); 4       return res 5 }

  封裝一個解壓縮的函數(里面用到的方法都是pako寫好的,直接調用),代碼:

 1 var pako = require('pako');  2
 3 page({  4  ...  5  unzip(b64Data){  6     let strData = atob(b64Data),  7         charData = strData.split('').map(function(x){return x.charCodeAt(0);}),  8         binData = new Uint8Array(charData),  9         data = pako.inflate(binData); 10     strData = String.fromCharCode.apply(null, new Uint16Array(data)); 11     return decodeURIComponent(strData) 12  } 13 })        

  然后將接口拿到的文章傳入到 unzip 中就可以解壓出來了。當然這只是我預期的結果(因為web端這樣的操作確實可行)

  真機調試后小程序報錯,找不到atob

  

  原因是pako方法中使用到window.atob,而小程序不支持這個方法,所以導致報錯。

  解決方法:引入atob的polyfill,就是在小程序實現一個atob方法

  atob polyfill 下載地址:https://github.com/davidchambers/Base64.js ( 該polyfill實現了atob和btoa)

1 const polyfill = require('../../utils/base64') 2 const {atob, btoa} = polyfill;

  引入atob后,再跑一遍真機測試,誒,舒服了,完美的展示出來,而且響應速度和原本的沒有什么差別

 

  然后我以為完成任務了,在測試一篇稍微大點的文章時(260k左右),小程序再次報錯

  

  而且居然是調用棧內存溢出。wtf?!初步我還以為自己邏輯寫錯,導致出現遞歸死循環之類的。檢查幾遍后,並沒有發現錯誤。只能再次求助百度...

  得到的原因是因為數據量過大,導致在進行 String.fromCharCode.apply(null, new Uint16Array(data)) 時,出現棧內存溢出的問題,用以下的函數代替這步即可:

 1 function handleCodePoints(array) {  2     var CHUNK_SIZE = 0x8000; // arbitrary number here, not too small, not too big
 3     var index = 0;  4     var length = array.length;  5     var result = '';  6     var slice;  7     var arr = [];  8     for (var i = 0, _i = array.length; i < _i; i++) {  9         arr[i] = array[i]; 10  } 11     while (index < length) { 12         slice = arr.slice(index, Math.min(index + CHUNK_SIZE, length)); // `Math.min` is not really necessary here I think
13         result += String.fromCharCode.apply(null, slice); 14         index += CHUNK_SIZE; 15  } 16     return result; 17 }

寫在最后

  后面測試過程中並未出現其他問題,測試了更大的數據量后也沒什么問題。至此,我在小程序使用pako.js之路告一段落。之后如果還有存在問題,我會繼續更新這篇文章。若你在使用過程中發現其他問題,請告訴我。


免責聲明!

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



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