javascript是单线程的,会阻塞程序执行,ajax常用于和服务器交互数据,虽然不会阻塞程序,但改不了单线程的本质。针对这个缺点,h5出了新的功能worker,支持多线程。
worker可以创建子线程,子线程会在新的环境中执行,不会阻塞主线程。
Worker还有子类-SharedWorker 共享线程,常用于浏览器不同标签页之间进行通讯,具体可以看这里。
ie10以下不支持,其它基本无问题
兼容性判断:if (!Worker) { throw new Error('当前浏览器不支持多线程') }
const childThread = new Worker("ChildThread.js");
postMessage()
方法来发送消息onmessage = (e)=>{}
,或者 addEventListener('message', (e)=>{})
这里使用最简单的demo来说明使用方式,下面demo主线程向子线程发了一条信息,子线程收到后返回一条信息。
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>
child/ChildThread.js
// 接收主线程信息
self.addEventListener('message', (e) => {
console.log('子线程收到主线程信息:', e.data)
postMessage('I am fine.')
})
线程结束的时候可以手动关闭,否则会一直常驻。
主线程关闭子线程方式:worker.terminate()
子线程内部关闭方式:self.close()
当子线程发生错误的时候,主线程可以通过添加监听来处理
worker.addEventListener('error', (e)=>{});
在子线程里,可以使用importScripts导入外部js文件,方式是:
importScripts('script1.js', 'script2.js')
子线程里面可以再次通过 new Worder('**.js')
来建立自身的子线程,实现线程嵌套,处理复杂业务
子线程的上下文为自身,可以通过self,或者this来获取;
主线程和子线程之间传递的消息是复制而不是共享,也就是说如果传递参数是一个对象,那么程序会使用JSON方式来编码/解码对象;
主线程和子线程是不同上下文,不同作用域,子线程不能调用主线程的dom和方法,具体
不能使用:
可以使用:
建立子线程js:根目录/public/worker/ChildThread.js
,代码如下:
// 接收主线程信息
self.addEventListener('message', (e) => {
console.log('Worker子线程收到主线程信息:', e.data)
postMessage('I am fine.')
})
建立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>
在vue中可以通过vue-worker这个库来使用worker,语法有所不同。
npm i -S vue-worker
在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)
})
(第二个参数必须是数组)
,同时定义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
兄弟,都看到这里了,点个赞再走呗