记学习Web Worker的使用

390 阅读3分钟

前言:记一次学习过程。

js是一门单线程的语言,但是在Web Worker中允许开启子线程去进行计算。

来自MDN:
Web Worker为Web内容在后台线程中运行脚本提供了一种简单的方法。线程可以执行任务而不干扰用户界面。此外,他们可以使用XMLHttpRequest执行 I/O  (尽管responseXMLchannel属性总是为空)。一旦创建, 一个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。