vue 中使用 web worker

首先了解一下什么是 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


image.png

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文件


image.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容