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('当前浏览器不支持多线程') }
2、创建
- 创建子线程的js文件:ChildThread.js
- 创建子线程
const childThread = new Worker("ChildThread.js");
3、通讯
- 主线程和子线程都是通过
postMessage()
方法来发送消息 - 接收消息都是使用
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结果输出
5、关闭
线程结束的时候可以手动关闭,否则会一直常驻。
主线程关闭子线程方式:worker.terminate()
子线程内部关闭方式:self.close()
6、错误处理
当子线程发生错误的时候,主线程可以通过添加监听来处理worker.addEventListener('error', (e)=>{});
7、导入文件
在子线程里,可以使用importScripts导入外部js文件,方式是:importScripts('script1.js', 'script2.js')
8、多线程嵌套
子线程里面可以再次通过 new Worder('**.js')
来建立自身的子线程,实现线程嵌套,处理复杂业务
四、Worker使用注意项
- 子线程的上下文为自身,可以通过self,或者this来获取;
- 主线程和子线程之间传递的消息是复制而不是共享,也就是说如果传递参数是一个对象,那么程序会使用JSON方式来编码/解码对象;
- 主线程和子线程是不同上下文,不同作用域,子线程不能调用主线程的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使用
- 在create里面创建线程 worker,定义好对不同message的回调方法;
- 通过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
兄弟,都看到这里了,点个赞再走呗