JS Worker介绍及在vue中使用

  • 一、Worker介绍
  • 二、Worker应用场景
  • 三、Worker使用
  • 1、兼容性
  • 2、创建
  • 3、通讯
  • 4、最简单demo
  • 4.1主线程html页面
  • 4.2子线程代码
  • 4.3结果输出
  • 5、关闭
  • 6、错误处理
  • 7、导入文件
  • 8、多线程嵌套
  • 四、Worker使用注意项
  • 五、vue中使用Worker
  • 1、常规使用
  • 1.1 建立子线程js
  • 1.2 vue文件使用
  • 2、vue-worker使用
  • 2.1vue-worker安装
  • 2.2注册
  • 2.3使用


一、Worker介绍

javascript是单线程的,会阻塞程序执行,ajax常用于和服务器交互数据,虽然不会阻塞程序,但改不了单线程的本质。针对这个缺点,h5出了新的功能worker,支持多线程。
worker可以创建子线程,子线程会在新的环境中执行,不会阻塞主线程。

Worker还有子类-SharedWorker 共享线程,常用于浏览器不同标签页之间进行通讯,具体可以看这里

二、Worker应用场景

  • 加密大量数据
  • 读取并解析大json文件
  • 突出显示代码语法或其他实时文本格式
  • 拼写检查
  • 分析视频或音频数据
  • 处理超大数组

三、Worker使用

1、兼容性

ie10以下不支持,其它基本无问题

兼容性判断:if (!Worker) { throw new Error('当前浏览器不支持多线程') }

vue使用element ui header Vue使用shareWorker_主线程

2、创建

  1. 创建子线程的js文件:ChildThread.js
  2. 创建子线程 const childThread = new Worker("ChildThread.js");

3、通讯

  1. 主线程和子线程都是通过 postMessage() 方法来发送消息
  2. 接收消息都是使用onmessage = (e)=>{},或者 addEventListener('message', (e)=>{})

4、最简单demo

这里使用最简单的demo来说明使用方式,下面demo主线程向子线程发了一条信息,子线程收到后返回一条信息。

4.1主线程html页面

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Worder-简单示例</title>
  </head>
  <body>
    <h1>Worder-简单示例</h1>
    <h3>使用调试面板查看</h3>
    <script type="text/javascript">
      // 兼容性判断
      if (!Worker) {
        throw new Error('当前浏览器不支持多线程')
      }

      // 创建子线程
      const childThread = new Worker('child/ChildThread.js')

      // 向子线程发送数据
      childThread.postMessage('How are you?')

      // 监听子线程信息
      childThread.addEventListener('message', (e) => {
        console.log('主线程收到子线程信息: ', e.data)
      })

    </script>
  </body>
</html>

4.2子线程代码

child/ChildThread.js

// 接收主线程信息
self.addEventListener('message', (e) => {
  console.log('子线程收到主线程信息:', e.data)
  postMessage('I am fine.')
})

4.3结果输出

vue使用element ui header Vue使用shareWorker_子线程_02

5、关闭

线程结束的时候可以手动关闭,否则会一直常驻。
主线程关闭子线程方式:worker.terminate() 子线程内部关闭方式:self.close()

6、错误处理

当子线程发生错误的时候,主线程可以通过添加监听来处理
worker.addEventListener('error', (e)=>{});

7、导入文件

在子线程里,可以使用importScripts导入外部js文件,方式是:
importScripts('script1.js', 'script2.js')

8、多线程嵌套

子线程里面可以再次通过 new Worder('**.js') 来建立自身的子线程,实现线程嵌套,处理复杂业务

四、Worker使用注意项

  1. 子线程的上下文为自身,可以通过self,或者this来获取;
  2. 主线程和子线程之间传递的消息是复制而不是共享,也就是说如果传递参数是一个对象,那么程序会使用JSON方式来编码/解码对象;
  3. 主线程和子线程是不同上下文,不同作用域,子线程不能调用主线程的dom和方法,具体
    不能使用
  • window 对象
  • document 对象
  • parent 对象
  • alert()
  • confirm()

可以使用

  • navigator 对象
  • location 对象(只读)
  • XMLHttpRequest
  • setTimeout()/clearTimeout() 和 setInterval()/clearInterval()
  • 应用缓存
  • 使用 importScripts() 方法导入外部脚本
  • 生成其他 Web Worker

五、vue中使用Worker

1、常规使用

1.1 建立子线程js

建立子线程js:根目录/public/worker/ChildThread.js,代码如下:

// 接收主线程信息
self.addEventListener('message', (e) => {
  console.log('Worker子线程收到主线程信息:', e.data)
  postMessage('I am fine.')
})

1.2 vue文件使用

建立vue文件,代码如下

<template>
  <div><h1>worker使用</h1></div>
</template>

<script>
export default {
  created() {
    // 兼容性判断
    if (!window.Worker) {
      throw new Error('当前浏览器不支持多线程')
    }

    // 创建子线程
    this.childThread = new Worker('/worker/ChildThread.js')

    // 向子线程发送数据
    this.childThread.postMessage('How are you?')

    // 监听子线程信息
    this.childThread.addEventListener('message', this.messageHandle)
  },
  methods: {
    // 消息处理
    messageHandle(e) {
      console.log('Worker主线程收到子线程信息: ', e.data)
    },
  },
  destroyed() {
    // 记得销毁线程
    this.childThread.removeEventListener('message', this.messageHandle)
    this.childThread.terminate()
  },
}
</script>

2、vue-worker使用

在vue中可以通过vue-worker这个库来使用worker,语法有所不同。

2.1vue-worker安装

npm i -S vue-worker

2.2注册

在main.js引入

import Vue from 'vue'
import VueWorker from 'vue-worker'
import App from 'App.vue'

Vue.use(VueWorker)

new Vue({
  el: '#app',
  render: h => h(App)
})

2.3使用

  1. 在create里面创建线程 worker,定义好对不同message的回调方法;
  2. 通过postMessage方法向子线程发送消息(第二个参数必须是数组),同时定义then处理回调,定义catch处理异常
<template>
  <div><h1>vue-worker使用</h1></div>
</template>

<script>
export default {
  created() {
    // 创建子线程
    this.worker = this.$worker.create([
      {
        message: 'to child',
        func: (data) => {
          console.log('子线程收到主线程信息:', data)
          return 'i am fine'
        },
      },
    ])

    // 主线程发生消息
    this.worker
      // postMessage第二个参数必须是数组
      .postMessage('to child', ['how are you'])
      .then((res) => {
        console.log('主线程收到子线程信息:', res)
      })
      .catch((e) => {
        console.error(e)
      })
  },
  destroyed() {
    // 记得销毁线程
    this.worker = null
  },
}
</script>

上例是vue-worker使用的最简单demo

兄弟,都看到这里了,点个赞再走呗