1. 简单使用
- 介绍
Web Worker
的作用,就是为 JavaScript
创造多线程环境,允许主线程创建 Worker
线程,将一些任务分配给后者运行。
在主线程运行的同时,Worker
线程在后台运行,两者互不干扰。等到 Worker
线程完成计算任务,再把结果返回给主线程。
-
Web Worker
简单使用
Web Worker
示例
//main.js
const first = document.querySelector('#number1');
const second = document.querySelector('#number2');
const result = document.querySelector('.result');
if (window.Worker) {
const myWorker = new Worker("worker.js");
first.onchange = function() {
myWorker.postMessage([first.value, second.value]);
}
second.onchange = function() {
myWorker.postMessage([first.value, second.value]);
}
myWorker.onmessage = function(e) {
result.textContent = e.data;
}
myWorker.onerror = function (e) {
console.log(['ERROR: ', e.lineno, ' in ', e.filename, ': ', e.message].join(''));
};
}
//worker.js
onmessage = function(e) {
const result = e.data[0] * e.data[1];
if (isNaN(result)) {
postMessage('Please write two numbers');
} else {
const workerResult = 'Result: ' + result;
postMessage(workerResult);
}
}
-
Web Worker
使用限制
(1) 同源限制
分配给 Worker
线程运行的脚本文件,必须与主线程的脚本文件同源。
(2) DOM
限制
Worker
线程所在的全局对象,与主线程不一样,无法读取主线程所在网页的 DOM
对象,也无法使用document
、window
、parent
这些对象。但是,Worker
线程可以navigator
对象和location
对象。
(3) 通信联系
Worker
线程和主线程不在同一个上下文环境,它们不能直接通信,必须通过消息完成。
(4) 脚本限制
Worker
线程不能执行alert()
方法和confirm()
方法,但可以使用 XMLHttpRequest
对象发出AJAX
请求。
(5) 文件限制
Worker
线程无法读取本地文件,即不能打开本机的文件系统(file://
),它所加载的脚本,必须来自网络。
-
Worker
线程一旦新建成功,就会始终运行,比较耗费资源。使用完毕必须关闭。
(1) 主线程终止worker
myWorker.terminate();
(2) worker
线程终止worker
close();
- 数据通信
主线程与 Worker
之间的通信内容,可以是文本,也可以是对象。
Structured Clone
是 postMessage
默认的通信方式。这种通信是拷贝关系,即是传值而不是传址,Worker
对通信内容的修改,不会影响到主线程。
主线程与 Worker
也可以交换二进制数据,比如 File
、Blob
、ArrayBuffer
等类型。
- 兼容性
主流浏览器在几年前就支持Worker
。
image.png
2. Web Worker 文献综述
-
web worker
和setTimeout / Promise.all
区别
JS 单线程中的“并发”通过Event Loop
实现不同Task
的上下文切换 (Context Switch
)。这些 Task
通过 BOM API
调起其他线程为主线程工作, 但回调函数代码逻辑依然由 JS 串行运行。
Web Worker
是 JS
多线程运行技术。
- 拆分同步逻辑的异步方案
将同步任务拆分为多个小于 16ms
的子任务, 然后在页面每一帧前通过 requestAnimationFrame
按计划执行一个子任务, 直到全部子任务执行完毕。
拆分同步逻辑存在以下几个问题:
(1) 不是所有 js
逻辑都可拆分
比如数组排序, 树的递归查找, 图像处理算法等。
(2) 可以拆分的逻辑难以把控粒度
拆分的子任务在高性能机器上可以控制在16ms
内, 但在性能落后机器 上就超过了。
- 性能提升
(1) 多线程与CPU
核数
Worker
多线程并不会直接带来计算性能的提升, 能否提升与设备CPU
核数和线程策略有关。真正带来性能提升的是多核多线程并发。
(2) 通信速度
提升的性能 = 并行提升的性能 – 通信消耗的性能
- 数据传输方式
(1) Structured Clone
Structured Clone
是 postMessage
默认的通信方式。复制一份线程 A
的 JS Object
内存给到线程 B
, 线程B
能获取和操作新复制的内存。
简单有效地隔离不同线程内存, 避免冲突。但Object
规模过大时, 会占用大量的线程时间。
兼容性:较好
(2) Transfer Memory
线程A
将指定内存的所有权和操作权转给线程B
, 转让后线程A
无法再访问这块内存。
Transfer Memory
以失去控制权来换取高效传输, 通过内存独占给多线程并发加锁。
兼容性:IE11+
(3) Shared Array Buffer
Shared Array Buffer
是共享内存, 线程A
和线程B
可以同时访问和操作同一块内存空间,数据共享。
多个并行的线程共享内存,会产生竞争问题,不像前 2 种传输方式默认加锁。
兼容性:只有Chrome 68+支持.
-
Web Worker
适用场景
(1) 2010
年, The Basics of Web Workers
数据处理、文本处理、图像/视频处理、网络处理
(2) 2018 年, Parallel programming in JavaScript using Web Workers
Canvas drawing
(离屏渲染方面)、Virtual DOM diffing
(前端框架方面)、indexedDB
(本地存储方面)、Webassembly
(编译型语言方面)
参考资料
网友评论