Web Workers总结

60次阅读

共计 4269 个字符,预计需要花费 11 分钟才能阅读完成。

一.Web Workers 是什么
Web Workers 是 JavaScript 运行在浏览器中的一种能力, 它允许在主线程创建 Worker 线程, 主线程执行的同时,Worker 线程在后台运行, 互不干扰, 这并不是说 JavaScript 本身具有多线程的能力, 是 js 运行在 webkit 浏览器中, 浏览器为其启动了新的线程, 从而实现多线程的功能.
二.Web Workers 分类
Web Workers 中主要的两种线程为专用线程 Dedicated Worker 和共享线程 Shared Worker, 专用线程供单页面使用, 即专用线程不能被多个不同的页面使用, 共享线程能被多个不同的页面使用.
2.1. 专用线程(Dedicated Worker)
2.1.1 专用线程实例
在输入框输入一个数, 计算出从 1 到该数字的和
(1). 主线程代码
<!DOCTYPE html>
<html>
<head>
<meta http-equiv=”Content-Type” content=”text/html; charset=utf-8″ />
<title></title>
</head>
<body>
<div class=”web-worker”>
<input type=”text” placeholder=” 请输入要计算到的数字 ” id=”num” />
<button onclick=”calculate()”> 计算 </button>
</div>
</body>
<script>
function calculate() {
var dom = document.getElementById(“num”);
var value = parseInt(dom.value, 10);
worker.postMessage(value);
}

var worker = new Worker(“worker.js”);
worker.onmessage = function(event) {
console.log(“receive data”, event.data);
worker.terminate(); // 终止 worker 进程
}
worker.onerror = function(error) {
console.log(“error==”, error.message, error.filename, error.lineno);
//error 错误信息:message 返回可读性良好的错误消息;filename 发生错误的脚本文件名;lineno 发生错误时所在脚本文件的行号
}
</script>
</html>
(2).Worker 线程代码(Worker 线程代码写在 worker.js 中)
onmessage = function(event) {
console.log(“worker event data”, event.data);
var value = event.data;
var sum = 0;
for (var i = 1; i < value; i++) {
sum += i;
}
postMessage(sum);
}

(3). 执行结果:
2.1.2 线程执行深度解析 根据以上述实例说明 (1). 首先调用 Worker 的构造函数新建一个 worker, 指定一个脚本 URI 去执行 worker 线程 (2). 通过 postMessage 发送给 worker 线程 (3). 在 worker 线程中用 onmessage 监听消息数据, 并接收封装在 event 参数 data 属性中的数据 (4).worker 将处理过的数据再通过 postMessage 发送给主线程 (5).worker 线程返回数据后, 执行主线程的 onmessage 回调函数, 调用 worker.terminate()终止线程执行, 当 worker 线程执行出错时会调用 onerror 回调函数.
详解: 代码执行到 var worker = new Worker(“worker.js”), 会在 webkit 内核中构造一个 webCore::jsWorker 对象, 并根据脚本地址发起异步加载流程, 此时主线程并不会阻塞, 等待 worker 线程的执行结果, 而是会接着往下执行. 接着主线程执行 postMessage, 这时 worker 线程还么有创建完成, 通过 input 输入框输入的数据将放在消息队列中等待, 直到 worker 线程创建完毕;worker 线程复制消息数据到 workerRunLoop 消息队列中,woker 线程处理消息数据后将数据通过自身的 postMessage 发送, 主线程执行 worker.onmessage 回调函数, 执行完毕后关闭线程. 如果主线程接着给 worker 线程发送数据消息,worker 线程会直接将复制消息数据到 WorkerRunLoop. 如图所示

2.1.3Transferrable objects 可转让对象 主线程和子线程之间可以通过结构化克隆算法 (复制副本) 的方式传入传出复制类型数据, 比如 File,Blob,ArrayBuffer 和 json 对象, 如果用 postMessag 传出一个 50MB 的文件将会非常消耗性能, 为了解决这个问题, 可以将主线程中的数据直接传递给 worker 线程这就是 Transferrable objects.
// Transferable Objects 格式 worker.postMessage(arrayBuffer, [arrayBuffer]);
// 例子 1
var ab = new ArrayBuffer(1);
worker.postMessage(ab, [ab]);
// 例子 2
var uInt8Array = new Uint8Array(1024*1024*32); // 32MB
for (var i = 0; i < uInt8Array .length; ++i) {
uInt8Array[i] = i;
}
worker.postMessage(uInt8Array.buffer, [uInt8Array.buffer]);
2.1.4 应用场景
(1). 预先缓存并抓取数据供后期使用
(2). 分析音视频数据,canvas 绘图数据的运算和图形生成处理
(3). 大量数据分析和计算处理
(4). 拼写检查
(5). 代码高亮处理或者其他一些页面文字格式化处理
2.1.5 总结 学习专用线程, 其实它可以和生活中的例子相结合起来, 比如领导给员工分配任务, 让 A 员工把产品的原型画出来后交给 B 员工去实现(领导作为主线程),A 员工在接收到任务 message 后开始工作, 工作的产出的原型就是 postMessage 要返回的数据,B 员工在没拿到原型时还做的他之前的工作, 收到 A 员工给的原型开始实现原型, 实现完成后将产出结果给领导演示. 结合这个例子可以理解专用线程的大致流程.
2.1.6 兼容性

2.2 共享线程(Shared Worker)
2.2.1 共享线程实例
两个页面分别给一个 SharedWorker 发送数据并接收同一个共享线程发送的数据

// A 页面 js 代码
var worker = new SharedWorker(“./worker.js”);
var port = worker.port;
console.log(“test port”, port);
port.postMessage(‘test000’);
port.onmessage = function(event) {
console.log(“test receive data”, event.data);
}
// B 页面 js 代码
var worker = new SharedWorker(‘worker.js’);
var port = worker.port;
console.log(“worker1 port”, port);
port.postMessage(‘test111’);
port.onmessage = function(event) {
console.log(“test1 receive data”, event.data);
};
//worker.js(即 SharedWorker)代码
onconnect = function(event) {
var port = event.ports[0];
port.onmessage = function(e) {
port.postMessage(e.data);
}
}

执行结果:
2.2.2 应用场景 共享线程主要用在同一个线程被多个页面或线程使用, 比如, 抓取缓存数据多个页面需要使用, 在浏览器兼容的情况下可以使用 ShareWorker.
2.2.3 总结在测试上述例子时, 用 google 浏览器测试, 共享线程中的例子不执行, 希望能得到解答和帮助
2.2.4 兼容性

三. 专用线程和共享线程的区别和注意事项
3.1 区别 (1) 共享 worker 通信必须通过端口对象 (一个确切的打开的端口) 供脚本与 worker 通信, 而专用线程在设置 onmessage 消息处理函数时会隐式的打开与主线程的端口连接.3.2 注意事项
(1). 在写 demo 测试时,Google 浏览器直接打开文件, 会当成是跨域问题, 报类似如下错误, 启用本地服务器测试就可以了
(2)分配给 Worker 线程运行的脚本文件,必须与主线程的脚本文件同源。
(3)worker 线程不能获取 DOM,window,document,parent 对象, 可以获取 navigator,Location,XMLHttpRequest 对象,setInterval/setTimeout 方法, Application Cache, 可以通过 importScripts()方法加载其他脚本, 可以创建新的 Web Worker。
四. 其他类型 Worker
4.1 ServiceWorkers(服务 worker)
一般作为 web 应用程序、浏览器和网络(如果可用)之前的代理服务器。它们旨在(除开其他方面)创建有效的离线体验,拦截网络请求,以及根据网络是否可用采取合适的行动并更新驻留在服务器上的资源。他们还将允许访问推送通知和后台同步 API。
4.2 Chrome Workers
是一种仅适用于 firefox 的 worker。如果您正在开发附加组件,希望在扩展程序中使用 worker 且有在你的 worker 中访问 js-ctypes 的权限,你可以使用 Chrome Workers。详情请参阅 ChromeWorker。
4.3 Audio Workers(音频 worker)
使得在 web worker 上下文中直接完成脚本化音频处理成为可能。
望不对之处请指正!
主要参考文章:
1.http://www.alloyteam.com/2015…2.https://developer.mozilla.org…3.http://www.ruanyifeng.com/blo…

正文完
 0