目录
- js单线程的问题
- webworker的基本使用
- webworker的常见应用
- 可视化优化
- 导出Excel
js单线程的问题
众所周知,js不擅长计算,计算是同步的,大规模的计算会让js主线程阻塞,导致界面完成卡死。比如有一个600多亿次的计算,在js中至少得花个2、3s,这2、3s主线程是阻塞的,界面是完全卡死的。异步可以解决js的单线程问题,但是异步不是解决js单线程的终极方案,异步只是把任务发布出去等着,后面还是会拉到主线程执行,异步不可能在异步队列里自己执行,所以一个耗时很高的操作,无论你做不做异步,他都会卡死你的页面,比如一个2、3s的计算丢到异步队列中去,并不会在异步队列中自己算完了,始终要等着回到主线程再进行计算。
webworker的基本使用
在主线程中创建一个webworker,并向webworker指明要执行的内容(要执行的内容放在js文件里,将js文件传递给webworker),注意这个js文件必须是线上地址,那我们可以把js文件放在public文件夹中,因为服务跑起来后,public文件夹作为静态资源目录是可以直接在线上访问的:
webworker执行完list.js的内容后,通过self.postMessage()
向主线程发送消息,主线程可以通过addEventListener("message",(e)=>{console.log(e.data})
来获取webworker向主线程发送的数据(也可以通过onMessage获取),主进程可以使用postMessage()
向webworker线程发送消息,webworker线程通过self.addEventListener("message",(e)=>{console.log(e.data})
来获取
假如交给new Worker(在线js文件)的在线文件不止一个,是分了模块的,就需要在list.js中引入其他的js(如a.js),使用importScript("a.js")
引入,注意a.js的地址也必须是网络地址,但他可以跨域,那就可以引入第三方库,可以挂别人的cdn
假如第三方模块使用es6的module规范写的,那么new Worker的时候需要说明:
此时,list.js引入a.js的时候可以使用import引入:
注意:
- webworker不能使用本地文件(即:
new Worker(在线js文件)
),必须是网络上的同源文件 - webworker不能使用window上的dom操作,也不能获取dom对象,dom相关的东西只有主线程有,只能做一些计算相关的操作。这就是vue、react没有使用webworker的原因,vue、react主要是针对dom节点做一些生成和计算,一些虚拟dom的比对可以交给webworker。
- 有的东西是无法通过主线程传递给子线程的,比如dom节点,一些对象里的特殊设置(freeze、getter、setter这些,所以vue的响应式对象是不能传递的),方法
- 模块的引入问题
webworker的常见应用
因为webworker的限制,就别想着多线程渲染dom了,因为他根本无法创建dom,所以vue和react没有考虑webworker,webworker主要应用于耗时的计算
- 随着webgl、canvas等能力的加入,web前端有越来越多的可视化操纵,比如在线滤镜,在线绘图,web游戏等,这些东西都是非常消耗计算的
- 一些后台管理系统也会涉及到一些,最常见的就是一些电子表单,比如10万条数据导出为Excel表格
可视化优化
实现图片加滤镜的效果:引入图片,通过drawImage将图片画到canvas上,然后点击过滤按钮,读取图片所有像素点(这张图片有160+w像素点,每个像素点有4个rgba值,那么就有600+w数据),对每个像素点循环100次进行加滤镜,合计60亿次计算。
点击页面过滤按钮后,主线程开始计算,页面没有反应,哪里都点不动,卡死,耗时800ms处理完成后页面才可以操作。如果将循环100次改为循环255次,则需要进行100+亿次计算,耗时2s多,页面卡死2s多。那我们可以把计算交给webworker,那么在webworker计算的时候,页面还能执行其他操作
导出Excel
往数组中push了10w个对象,点击导出按钮后,将10w条数据生成sheet表格并导出为一个excel对象。实际用户点击完导出按钮后,页面卡死,3、4s后Excel导出完毕,页面才能继续使用
使用webworker解决,这里使用了第三方xlsx库,我们可以找到xlsx的线上cdn地址传给new Worker,也可以从node_module中将xlsx库复制粘贴到public文件夹下,new Worker就引入这个地址,因为xlsx不是模块化的文件,所以excelworker使用import Script引入他