前言
目的:通过web worker对文件进行加密,以防止文件过大时,长时间阻塞主线程。
在vue项目中,如果直接使用,首先遇到的问题是worker文件路径与打包解析问题,因此需要搭配worker-loader来解析web worker。但这种方案不够简易,我们想要的是项目中引入便能直接使用的方法。
Let‘s Go!
方案一:将方法放至Public
我们可以把公用方法封装后,放入至public目录下。该目录下的文件并不会被Webpack处理,由此可以使用原生的web worker方式,但改方案依然很麻烦。
方案二:动态创建Web Worker
如上图所示,通过连续的转换可以将一个普通的函数转换为Web Worker。
下面我们来实现一个简单的demo (MD5)
// 子线程
const worker = () => {
// 引入库
self.importScripts('https://cdn.jsdelivr.net/npm/crypto-js@4.1.1/crypto-js.js');
onmessage = ({ data: { arrayBuffer } }) => {
const wordArray = self.CryptoJS.lib.WordArray.create(arrayBuffer);
const res = self.CryptoJS.MD5(wordArray).toString(); // MD5加密
postMessage({ data: res});
self.close(); // 关闭子线程
};
}
注意点:
- 方法的引入记得放在worker线程内
- 线程使用完毕后记得销毁
// 主线程
const createWorker = () => {
return new Promise((resolve, reject) => {
const reader = new FileReader();
const bloblUrl = URL.createObjectURL(new Blob([`(${worker.toString()})()`]))
reader.readAsArrayBuffer(file);
reader.onload = () => {
const worker = new Worker(bloblUrl);
worker.onmessage = ({ data: { data } }) => {
URL.revokeObjectURL(bloblUrl); // 释放
resolve(data);
};
const arrayBuffer = reader.result;
worker.postMessage(
{
arrayBuffer
},
[arrayBuffer]
);
};
reader.onerror = error => {
URL.revokeObjectURL(bloblUrl); // 释放
reject(error);
};
});
}
注意点:
- ArrayBuffer对象可以通过对象的转移,优化传递效率
- 通过URL.revokeObjectURL() 释放一个之前已经存在的、通过调用 URL.createObjectURL() 创建的URL 对象