
最近朋友跟我交流了一个场景 , 他有需求要用浏览器实时生成上万个二维码并打包压缩 。 现在功能是实现了 , 就是耗时长 , 而且一旦开始生成之后 , 页面卡顿的很厉害 。
我一听应该是 大量的 渲染 转化压缩 这类的计算阻塞了 Js执行主线程 导致的 , 于是开始尝试对方案进行优化 。
首先先复现Js主线程方案
这个方案心智负担最低 , 无非是 Canvas 渲染转化为 blob/(or others) jszip 添加 blob 并进行压缩 最后下载保存 , 执行的代码摘要如下:
import JSZip from 'jszip'async function download(){ // canvas do sth const zip = new JSZip() await new Promise((resolve)=>{ canvas.toBlob((blob) => { zip.file(filename blob!) resolve(blob) ) ) const content = await zip.generateAsync( { type: 'blob' ) saveAs(content zipName)
实现是非常简单的 。 笔者也复现了生成 10000 个二维码的 case , 在 qrcode 的 errorLevel 为 low 不进行额外压缩的情况下 。
每次生成图片大约 3-4kb(取决于携带参数的大小)生成时间约为 190257.10ms 压缩时间为 13531ms 总耗时 203788.10ms 。
后来经过反复测试 , 得出下列几个影响因素:
- 压缩等级越高 , 压缩越慢
- 生成图片体积越大 , 生成速度越慢 , 压缩速度也越慢
Worker多线程压缩
既然现在主线程被阻塞了 , 我们自然而然就想到了 Web Worker 于是笔者使用它来进行压缩图片的工作 。
在挑选测试素材时 , 使用了一张 16MB 的图片 , 尝试下来 , 压缩时间显著高于图片的生成时间 。 (体积较小图片其实是没有必要的 , 主线程本身压缩速度足够快)
worker 代码摘要如下:
// main.worker.tsimport JSZip from 'jszip'const worker: Worker = self as anyasync function doZip (arraybuffer: ArrayBuffer) { const zip = new JSZip() const filename = 'test.png' const blob = new Blob([arraybuffer
) zip.file(filename blob) const content = await zip.generateAsync( { type: 'arraybuffer' ({ percent ) => { // 压缩进度条 const event: MainWorkerEventData = { type: 'percent' percent worker.postMessage(event) ) const finish: MainWorkerEventData = { type: 'save' content: content worker.postMessage(finish [content
相关经验推荐
- 高通骁龙|从3699跌至1899,价格腰斩后的老旗舰,比千元机强大很多
- 联想|不输多屏协同!联想小新平板悄悄上线新功能:能把电脑装进去
- 耳机|获多个“年度最佳”的国产降噪耳机,为何能备受媒体青睐?
- 3d打印机|轮到美国被卡脖子,中国掌握一项世界顶尖技术,西方给多少也不卖
- 佳能|佳能相机是稳定可靠的工具,用过的镜头不太多,但没让我失望过
- 鼠标|电脑桌面怎样分屏显示?原来方法这么简单,可惜很多人都不知道
- OPPO|拿奖拿到手软!揽获多项“年度最佳”,OPPO Enco Free2系列稳了
- 雷蛇|搭载诸多顶尖配置,iQOO 9给游戏体验加buff
- sim卡|你熟悉的手机SIM卡,可能活不了多久了
- 爱普生|爱普生L6498墨仓式多功能一体机,刷新商用办公新体验
