概述
我们都知道JavaScript是一门单线程语言,其单线程带来了很大的不便。Web Worker的出现就是为JavaScript创造多线程的环境,运行主进程创建Worker线程,将一些任务分配给Worker线程运行。主线程运行的同时,Worker线程在后台运行,两者互不干扰。Worker线程计算的结果返回给主线程,这样主线程在面对计算密集型或高延迟的任务,就会比较流畅。
Web Worker的特点
- Worker线程一旦创建成功,就会始终运行。即使主线程卡死,它依然在运行。这样有利于与主线程通信,但是这也造成了Worker比较浪费资源,所以,一旦用完,我们就应该关闭它。
- 同源限制: 分配给Worker线程运行的脚本文件,必须与主线程的脚本文件同源
- DOM限制: 不能操作主线程中的DOM,要保持DOM的唯一性。
document
、window
、parent
这些对象都无法使用。可以使用navigator
、lacation(只读)
、XMLHttpRequest
、setTimeout
等API。 - 脚本限制: Worker线程不能执行
alert()、confirm()
这些方法。但可以使用 XMLHttpRequest 对象发出 AJAX 请求。 - 文件限制: 不可以读取本地文件(js主线程也不能)。出于安全性考虑,浏览器不允许js读取本地文件。
- 两类线程: Web Worker定义了两类工作线程:
专用线程
(只有一个页面可以使用这个线程)与共享线程
(多个同源页面可以共享一个线程)。
基本使用
主线程
-
创建Web Worker
主线程采用
new
命令,调用Worker()
构造函数,创建一个Worker线程:var worker = new Worker('work.js');
Worker()
构造函数的参数是一个脚本文件,该文件就是Worker线程要执行的任务, -
向Web Worker发送消息
主线程采用
worker.postMessage()
方法,向Worker发消息。worker.postMessage('hello'); worker.postMessage( {number: 10})
worker.postMessage()
中的参数,就是主线程传给Worker的数据。它可以是任意类型,包括二进制 -
主进程接受子线程发回的消息
worker.onmessage = function(event) { console.log('received worker message' + event.data); } // 或者 Worker.addEventListener('message', event => { console.log('received worker data', event.data); }, false);
-
主进程监听Worker是否发生错误
如果发生错误,Worker 会触发主线程的error事件。
worker.onerror(function (event) { // ... }) // 或者 worker.addEventListener('error', function (event) { // ... });
-
主线程关闭线程
Worker完成任务之后,主进程就可以关闭它。
worker.terminate();
Worker线程
-
监听来自主线程的数据
self.addEventListener('message' ,function(event) { self.postMessage('You said:' event.data); },false); // 等同于 this.addEventListener('message' ,function(event) { this.postMessage('You said:' event.data); },false);
self
表示子线程自身,当然也可以使用self.onmessage
来监听。self.postMessage()
方法用来向主线程发送消息。 -
Worker自身关闭
Worker线程可以在内部自己关闭,使用
close()
方法。 -
Worker加载脚本
Worker内部如果要加载其他脚本,有一个专门的方法
importScripts()
。importScripts('script1.js'); // 可以同时加载多个脚本 importScripts('script1.js', 'script2.js');
使用场景
- 数学运算
Web Worker最简单的应用就是用来做后台计算,对CPU密集型的场景再适合不过了。 - 图像处理
通过使用从<canvas>
中获取的数据,可以把图像分割成几个不同的区域并且把它们推送给并行的不同Workers来做计算,对图像进行像素级的处理,再把处理完成的图像数据返回给主页面。 - 大数据的处理
目前mvvm框架越来越普及,基于数据驱动的开发模式也越愈发流行,未来大数据的处理也可能转向到前台,这时,将大数据的处理交给在Web Worker也是上上之策了吧。
常用API总结
主线程中的API:
- worker.postMessage(): 主线程往worker线程发消息,消息可以是任意类型数据,包括二进制数据
- worker.terminate(): 主线程关闭worker线程
- worker.onmessage(): 指定worker线程发消息时的回调,也可以通过worker.addEventListener(‘message’,cb)的方式
- worker.onerror: 指定worker线程发生错误时的回调,也可以worker.addEventListener(‘error’,cb)
Worker线程中的API:
- self.postMessage: worker线程往主线程发消息,消息可以是任意类型数据,包括二进制数据
- self.close: worker线程关闭自己
- self.onmessage: 指定主线程发worker线程消息时的回调,也可以self.addEventListener(‘message’,cb)
- self.onerror: 指定worker线程发生错误时的回调,也可以 self.addEventListener(‘error’,cb)
参考文章: