首先了解一下什么是 web worker
Web Worker 的作用,就是为 JavaScript 创造多线程环境,允许主线程创建 Worker 线程,将一些任务分配给后者运行。在主线程运行的同时,Worker 线程在后台运行,两者互不干扰。等到 Worker 线程完成计算任务,再把结果返回给主线程。这样的好处是,一些计算密集型或高延迟的任务,被 Worker 线程负担了,主线程(通常负责 UI 交互)就会很流畅,不会被阻塞或拖慢。
通俗的讲就是 影分身,分出一个分身去做别的事情,既不耽误 自己做别的事情,很有意思。
主线程采用new命令,调用Worker()构造函数,新建一个 Worker 线程。
var worker = new Worker('work.js');
Worker 线程有一些自己的全局属性和方法。
self.name: Worker 的名字。该属性只读,由构造函数指定。
self.onmessage:指定message事件的监听函数。
self.onmessageerror:指定 messageerror 事件的监听函数。发送的数据无法序列化成字符串时,会触发这个事件。
self.close():关闭 Worker 线程。
self.postMessage():向产生这个 Worker 线程发送消息。
self.importScripts():加载 JS 脚本。
Worker 内部如果要加载其他脚本,有一个专门的方法importScripts()。 该方法可以同时加载多个脚本
importScripts('script1.js');
importScripts('script1.js', 'script2.js');
Worker 主要通过两个方法来传递信息
// worker.postMessage 发送信息
self.postMessage({method: 'echo', args: ['Work']});
// worker.onmessage 接收信息
self.onmessage = function (event) {
console.log('Received message ' + event.data);
// doSomething();
}
Worker 完成任务以后,主线程就可以把它关掉。
// 主线程
worker.terminate();
// Worker 线程
self.close();
还有很多 有兴趣可以看一下 阮一峰老师写的教程 很详细。
那么接下来直接进入正题
写一个简单地 上传 计算文件 hash值
首先在public下创建hash.js并且拿过来要用的js文件spark-md5.min.js
spark-md5.min.js 可以去GitHub 下载一下 或者 npm 安装 然后 找到复制过来
hash.js 如下
// hash.js
self.importScripts('spark-md5.min.js')
self.onmessage = e => {
const { chunks } = e.data
const spark = new self.SparkMD5.ArrayBuffer()
let count = 0
const loadNext = index => {
const reader = new FileReader()
reader.readAsArrayBuffer(chunks[index].file)
reader.onload = e => {
count++
spark.append(e.target.result)
if (count == chunks.length) {
self.postMessage({
hash: spark.end()
})
} else {
loadNext(count)
}
}
}
loadNext(0)
}
应用页面
<template>
<div>
<el-upload
class="upload-demo"
drag
action=""
multiple
:before-upload="beforeUpload"
:http-request="httpRequest"
>
<i class="el-icon-upload"></i>
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
</el-upload>
</div>
</template>
<script>
const CHUNK_SIZE = 0.1 * 1024 * 1024;
export default {
name: 'webWorker',
data() {
return {
chunks: [],
file: ''
}
},
methods: {
beforeUpload(file) {
this.file = file
},
//切割文件
createFileChunck(file, size = CHUNK_SIZE) {
const chunks = []
let cur = 0
while (cur < file.size) {
chunks.push({ index: cur, file: file.slice(cur, cur + size) })
cur += size
}
return chunks
},
// webWorker 计算hash
async calculateHashWorker() {
return new Promise(resolve => {
this.worker = new Worker('/hash.js')
this.worker.postMessage({ chunks: this.chunks })
this.worker.onmessage = e => {
const { hash } = e.data
if (hash) {
resolve(hash)
}
}
})
},
async httpRequest() {
// 计算hash
this.chunks = this.createFileChunck(this.file)
console.log(this.chunks);
const hash = await this.calculateHashWorker()
console.log('文件hash', hash)
}
}
}
</script>
<style scoped>
</style>
上传 一个文件 后得到一个 加密的hash值
并在网页中能找到 加载的 js文件