前言:记一次学习过程。
js是一门单线程的语言,但是在Web Worker中允许开启子线程去进行计算。
来自MDN:
Web Worker为Web内容在后台线程中运行脚本提供了一种简单的方法。线程可以执行任务而不干扰用户界面。此外,他们可以使用XMLHttpRequest执行 I/O (尽管responseXML和channel属性总是为空)。一旦创建, 一个worker 可以将消息发送到创建它的JavaScript代码, 通过将消息发布到该代码指定的事件处理程序(反之亦然)。 详细介绍
在Web Worker中不能操作DOM,也不能使用window对象的默认方法和属性。可以使用的函数和类
一.专享worker:只为父页面一个所用
1. 创建一个worker
通过调用 Worker 构造函数去创建一个worker
// index.js
// 检查浏览器是否支持Web Worker
if(window.Worker){
// 通过new Worker去创建一个worker线程
// 跟上worker.js文件的地址
let worker = new Worker('./worker.js')
}else {
alert('浏览器不支持Web Worker')
}
2. 线程之间的通讯
线程之间通过 postMessage() 进行通讯,接收消息通过 onmessage 事件接收
// 发送消息
// index.js
let worker = new Worker('./worker.js')
worker.postMessage('index向worker发送的消息')
// 接收消息
// worker.js
onmessage = function (e) {
console.log(e.data) // 'index向worker发送的消息'
}
线程之间不管是主线程向子线程发送消息,还是反过来,都是这种方式。
3. 关闭线程
分两种情况:主线程关闭和子线程自己关闭
// index.js
// 由主线程关闭
worker.terminate()
// worker.js
// 由子线程自己关闭
close()
4. 错误处理
/*
* 当线程运行现错误的时候,可以使用onerror事件来进行错误处理
* msg 错误性信息
* filename 发生错误的文件名
* lineno 发生错误的行号
* */
onerror = function (msg, filename, lineno) {
// do something
}
5. 使用subworkers
可以生成更多的worker,subworker也是依托于父页面的,引入的地址也是相对于父页面的地址来说的。
// worker.js
// 可调用全局函数importScripts()来引入新的worker
importScripts('./worker2.js', './subworker/workers3.js')
二.共享worker:可被多个脚本使用
值得注意的是,虽然可以被多个脚本使用,但这些脚本必须得同源(协议,端口号,域名相同)
1. 创建共享worker
通过调用 SharedWorker 构造函数去创建一个共享worker
// index1.js
let worker = new SharedWorker('./worker.js')
// index2.js
let worker = new SharedWorker('./worker.js')
值得注意的是,同一个地址只会创建一个共享worker,当其他页面使用这个地址创建时,会进行复用。
2. 通讯前提
线程之间是通过端口去进行通讯的,所以在传递消息之前,端口必须被显式地打开,打开方式以下有两种:
- 使用 onmessage 事件处理函数
- 调用 start 方法 调用start方法只有一种情况,那就是消息时间正在被 addEventListener 调用的时候。
// 第一种方法
// index1.js
let worker = new SharedWorker('./worker.js')
worker.onmessage = function(e){
// do something
}
// 第二种方法,必须通过端口 port 调用
// index1.js
worker.port.start()
// worker.js
port.start()
3. 线程之间的通讯
// index1.js
let worker = new SharedWorker('./worker.js')
worker.port.onmessage = function(e){
console.log(e.data)
}
worker.port.postMessage('index1发送的消息')
// worker.js
// 使用 onconnect 进行连接
onconnect = function(event){
// 使用 port 进行通讯
let { ports } = event
let port = ports[0]
port.onmessage = function(e){
port.postMessage('worker发送的消息')
}
}
以上都没有用 start 进行连接,因为使用了 onmessage 事件处理函数。
4. 错误处理
同专享worker
5. chrome调试worker小技巧
在f12的控制台中看不见 worker.js 文件中的输出,可以用以下方法:
- 在地址栏输入 chrome://inspect
- 点击 Shared workers
- 对应的 worker 下点击 inspect
- 在弹出的控制台中可以方便地使用 console.log 等进行调试
over。