Web Worker 的使用

Youky ... 2022-10-16 前端
  • 性能优化
  • JS
About 1 min

# Web Worker 的使用

# 1. 意义

由于 JS 是单线程的,费时的 JS 操作将会导致整个页面的阻塞。Web Worker 提供了创建多线程的方法,将一些耗时且 UI 无关的工作交给 worker,可提高页面的使用体验。

限制:

  • 同源策略:worker 线程执行的脚本要和当前页面同源
  • API 限制:
    • 不能操作 DOM
    • 不能使用 window 的全局变量,但可以使用 navigator 和 location 对象
    • 不能使用 alert、confirm 方法
    • 无法读取本地文件
  • 和主线程不在一个上下文环境,通讯要通过 postMessage 完成

# 2. 主线程的使用

# 创建

创建一个子线程,要传入一个脚本的 URL。如果该脚本加载失败,则 Worker 会静默失败

const worker = new Worker('url');
1

如果要在本文件中描述执行的内容,可以用 Blob 和 window.URL.createObjectURL 生成一个 URL

function createWorker(f) {
  const blob = new Blob(['(' + f.toString() +')()']);
  const url = window.URL.createObjectURL(blob);
  const worker = new Worker(url);
  return worker;
}
1
2
3
4
5
6

# 通信

  1. 主线程 => 子线程
worker.postMessage(param);
1

参数可以是任意类型,包括二进制数据。但传递是拷贝形式而不是引用形式。因此对于大数据会存在性能问题。

  1. 子线程 => 主线程
worker.onmessage = function (event) {
  console.log('Received message ' + event.data);
}
1
2
3

# 错误处理

worker.onerror(function (e) {
  console.log([
    'ERROR: Line ', e.lineno, ' in ', e.filename, ': ', e.message
  ].join(''));
});
1
2
3
4
5

# 关闭

worker.terminate();
1

# 3. 子线程的使用

子线程中无法使用 window,self 代表全局对象

# 和主线程的通信

  1. 主线程 => 子线程
self.addEventListener('message', function (e) {
  self.postMessage('Received: ' + e.data);
}, false);
1
2
3
  1. 子线程 => 主线程
self.postMessage('something');
1

# 加载其他脚本

在子线程中加载其他脚本:

importScripts('script1.js', 'script2.js');
1

# 关闭

self.close();
1
Last update: October 16, 2022 21:28
Contributors: Youky