JS进阶
子线程处理
问题:今天做到一个需求要求前端上传文件时检查MD5值,这里使用了spark-md5来分块计算MD5值。在小文件计算时非常顺利,在上传一个700MB文件的时候就出现了线程明显的卡断,导致整个Vue页面未响应了几秒才开始上传文件。
原因剖析
JavaScript在前端是异步单线程的,如果要计算一个大文件md5值会导致主线程直接被阻塞掉,UI界面自然会未响应。
这里采用创建子js线程的方式,并且以Promise的方式来异步的获取结果。
var myWorker = new Worker('../js/md5Worker.js');
创建一个MD5工作线程对象myWorker.postMessage([file]);
需要传入线程的参数数组,这里传递了文件信息。myWorker.onmessage = onMessage;
绑定回调方法
这样子el-upload组件就会在工作线程完成md5解析工作后获取到返回异步操作结果,然后执行上传的逻辑。
el上传前钩子
beforeUpload(file){
/*推送上传消息*/
let info = {
/*文件uid*/
uid:file.uid,
/*文件名*/
name:file.name,
/*状态*/
status:null,
/*进度条百分比*/
progressPercent:0,
};
this.$store.state.uploadInfoMap.set(file.uid,info);
this.$store.commit('uploadStart');
return new Promise((resolve, reject) => {
/*创建一个新线程去处理*/
var myWorker = new Worker('../js/md5Worker.js');
/*为线程传递消息*/
myWorker.postMessage([file]);
/*计算函数*/
let md5;
let onMessage = (e)=>{
{
md5 = e.data;
file.md5 = md5;
resolve();
}
}
/*绑定回调方法*/
myWorker.onmessage = onMessage;
})
},
worker子线程
importScripts('../utils/spark-md5.js');
self.onmessage = function(e) {
/* console.log('Message received from main script');*/
let fileReader = new FileReader()
let spark = new SparkMD5.ArrayBuffer() // 创建md5对象(基于SparkMD5)
fileReader.readAsArrayBuffer(e.data[0]) // file 对应上传的文件
// 文件读取完毕之后的处理
fileReader.onload = (e) => {
spark.append(e.target.result);
let md5 = spark.end();
/* console.log('Posting message back to main script');*/
self.postMessage(md5);
}
}
通过
e.data[index]
来获取传入的参数调用
self.postMessage(result)
来返回结果
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以邮件至 1300452403@qq.com