动态创建Web Worker进行文件加密

525 阅读1分钟

前言

目的:通过web worker对文件进行加密,以防止文件过大时,长时间阻塞主线程。

在vue项目中,如果直接使用,首先遇到的问题是worker文件路径与打包解析问题,因此需要搭配worker-loader来解析web worker。但这种方案不够简易,我们想要的是项目中引入便能直接使用的方法。

Let‘s Go!

方案一:将方法放至Public

我们可以把公用方法封装后,放入至public目录下。该目录下的文件并不会被Webpack处理,由此可以使用原生的web worker方式,但改方案依然很麻烦。

方案二:动态创建Web Worker

screenshot-20220609-224834.png

如上图所示,通过连续的转换可以将一个普通的函数转换为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();  // 关闭子线程
  };
}

注意点:

  1. 方法的引入记得放在worker线程内
  2. 线程使用完毕后记得销毁
// 主线程
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);
    };
  });
}

注意点:

  1. ArrayBuffer对象可以通过对象的转移,优化传递效率
  2. 通过URL.revokeObjectURL() 释放一个之前已经存在的、通过调用 URL.createObjectURL() 创建的URL 对象

THANKS FOR WATCHING~