需求:在大文件进行切片上传时,整个过程会产生大量计算,导致阻塞主线程运行,使用户界面不可操作,因此考虑将文件切片的处理过程放到worker线程中进行,以此来缓解主线程压力。
众所周知,JavaScript 是单线程的。一些复杂而又耗时的操作,势必会阻塞页面的渲染/交互,影响用户体验。web worker 允许开发者为页面额外开启一个线程,用来处理复杂而耗时的操作,不会阻塞主线程,从而达到优化用户体验的目的。
在Vue中的使用
1.安装worker-loader
cnpm i -D worker-loader
2.在vue.conf.js中配置loader
module.exports = {
chainWebpack: config => {
// 将匹配到的文件使用worker-loader处理
config.module
.rule('worker')
.test(/\.worker\.js$/) // 匹配文件名为xxx.worker.js的文件
.use('worker-loader')
.loader('worker-loader')
.end()
config.module.rule('js').exclude.add(/\.worker\.js$/)
}
}
配置好后重启项目。
3.实例化Worker
新建sliceUpload.worker.js文件,并在vue文件内导入
主线程:
<script>
import Worker from './sliceUpload.worker.js'
export default {
data() {
return {
subWorker: null
}
},
mounted() {
this.initWebWorker()
},
methods: {
initWebWorker() {
// 由于worker-loader的引入,所以在实例化Worker时不用传参
this.subWorker = new Worker()
// 向worker线程发送数据
this.subWorker.postMessage({ a:1, b:2 })
// 监听worker线程发送回来的数据
this.subWorker.onmessage = (msg) => {
// dosomething
}
}
}
}
</script>
worker线程:
// 由于业务需要,我需要引入三方库(ajax和文件切片工具)
// 将文件下载至项目本地的public文件夹下然后使用 importScripts导入脚本
// 由于worker线程没有window上下文,直接引入三方库可能会导致window is not defined错误, 所以在worker线程内定义一个全局变量window防止报错
window = self
importScripts('/script/jquery-nodom.js', '/script/slice.min.js')
// 监听主线程传过来的数据
addEventListener('message', function (e) {
// dosomething
// 向主线程发送数据
postMessage(xxxx)
})
4.进行测试
经过对比使用worker发现,使用worker后文件切片浏览器UI不在卡顿,非常丝滑。