Web Worker是什么
.Web Worker是什么
Web Worker 是HTML5标准的一部分,这一规范定义了一套 API,它允许一段JavaScript程序运行在主线程之外的另外一个线程中。Web Worker 规范中定义了两类工作线程,分别是专用线程Dedicated Worker和共享线程 Shared Worker,其中,Dedicated Worker只能为一个页面所使用,而Shared Worker则可以被多个页面所共享,本文示例为专用线程Dedicated Worker。
1.1 API快速上手
使用Dedicated Worker的主页面代码main.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
var worker = new Worker("task.js");
worker.postMessage(
{
id:1,
msg:'Hello World'
}
);
worker.onmessage=function(message){
var data = message.data;
console.log(JSON.stringify(data));
worker.terminate();
};
worker.onerror=function(error){
console.log(error.filename,error.lineno,error.message);
}
|
Dedicated Worker所执行的代码task.js
1
2
3
4
5
|
onmessage = function(message){
var data=message.data;
data.msg = 'Hi from task.js';
postMessage(data);
}
|
在main.js代码中,首先通过调用构造函数,传入了worker脚本文件名,新建了一个worker对象,在我的理解中,这一对象是新创建的工作线程在主线程的引用。随后调用worker.postMessage()方法,与新创建的工作线程通信,这里传入了一个json对象。随后分别定义了worker对象的onmessage事件和onerror事件的回调处理函数,当woker线程返回数据时,onmessage回调函数执行,数据封装在message参数的data属性中,调用 worker 的 terminate()方法可以终止worker线程的运行;当worker线程执行出错时,onerror回调函数执行,error参数中封装了错误对象的文件名、出错行号和具体错误信息。
在task.js代码中,定义了onmessage事件处理函数,由主线程传入的数据,封装在message对象的data属性中,数据处理完成后,通过postMessage方法完成与主线程通信。在工作线程代码中,onmessage事件和postMessage方法在其全局作用域可以访问。
1.2 worker线程执行流程
通过查阅资料,webKit加载并执行worker线程的流程如下图所示
1) worker线程的创建的是异步的
代码执行到"var worker = new Worker(task.js')“时,在内核中构造WebCore::JSWorker对象(JSBbindings层)以及对应的WebCore::Worker对象(WebCore模块),根据初始化的url地址"task.js"发起异步加载的流程;主线程代码不会阻塞在这里等待worker线程去加载、执行指定的脚本文件,而是会立即向下继续执行后面代码。
2) postMessage消息交互由内核调度
main.js中,在创建woker线程后,立即调用了postMessage方法传递了数据,在worker线程还没创建完成时,main.js中发出的消息,会先存储在一个临时消息队列中,当异步创建worker线程完成,临时消息队列中的消息数据复制到woker对应的WorkerRunLoop的消息队列中,worker线程开始处理消息。在经过一轮消息来回后,继续通信时, 这个时候因为worker线程已经创建,所以消息会直接添加到WorkerRunLoop的消息队列中;
1.3 worker线程数据通讯方式
主线程与子线程数据通信方式有多种,通信内容,可以是文本,也可以是对象。需要注意的是,这种通信是拷贝关系,即是传值而不是地址,子线程对通信内容的修改,不会影响到主线程。事实上,浏览器内部的运行机制是,先将通信内容串行化,然后把串行化后的字符串发给子线程,后者再将它还原。
主线程与子线程之间也可以交换二进制数据,比如File、Blob、ArrayBuffer等对象,也可以在线程之间发送。但是,用拷贝方式发送二进制数据,会造成性能问题。比如,主线程向子线程发送一个50MB文件,默认情况下浏览器会生成一个原文件的拷贝。为了解决这个问题,JavaScript允许主线程把二进制数据直接转移给子线程,转移后主线程无法再使用这些数据,这是为了防止出现多个线程同时修改数据的问题,这种转移数据的方法,叫做Transferable Objects。
1
2
3
4
5
6
|
// Create a 32MB "file" and fill it.
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]);
|
1.4 API进阶
在worker线程中,可以获得下列对象
1) navigator对象
2) location对象,只读
3) XMLHttpRequest对象
4) setTimeout/setInterval方法
5) Application Cache
6) 通过importScripts()方法加载其他脚本
7) 创建新的Web Worker
worker线程不能获得下列对象
1) DOM对象
2) window对象
3) document对象
4) parent对象
上述的规范,限制了在worker线程中获得主线程页面相关对象的能力,所以在worker线程中,不能进行dom元素的更新。
2. 似曾相识worker模型
我在学习Web Worker过程中,总有一种似曾相似的感觉。在以往的学习经验中,了解过Java Swing GUI库中的Swing Worker,我们可以看看worker模型在Swing中的应用。
2.1 Swing事件分发模型
同Winform/WPF等其他GUI库一样,Swing是一个基于事件队列的单线程编程模型。Swing将GUI请求放入一个事件队列EventQueue 中等待执行,EventQueue的派发机制由单独的一个线程管理,这个线程称为事件派发线程(EventDispatchThread),负责GUI组件的绘制和更新。这一事件分发模型如下图所示:
Swing单线程模型的一个问题是,如果在“事件派发线程”上执行的运算太多,那么GUI界面就会停住,系统响应和运算就会非常缓慢。
既然事件派发线程是为了处理GUI事件而设的,那么,我们只应该把GUI事件处理相关的代码,放在事件派发线程中执行。其他与界面无关的代码,应该放在Java其他的线程中执行。这样,我们在Swing的事件处理中,仍然使用Swing的单线程编程模型,而其他业务操作均使用多线程编程模型,这就可以大大提高Swing程序的响应和运行速度,充分运用Java多线程编程的优势。
2.2 Swing Worker
Java SE 6提供了javax.swing.SwingWorker类,Swing Worker 设计用于需要在后台线程中运行长时间运行任务的情况,并可在完成后或者在处理过程中向 UI 提供更新。
假定我们在UI界面点击一次下载按钮,在按钮的事件处理函数中,需要去加载一张Icon图片,图片加载完成后,将icon在UI界面展示出来。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
SwingWorker testWorker = new SwingWorker<Icon , Void>(){
@Override
protected Icon doInBackground() throws Exception {
Icon icon = retrieveImage(strImageUrl);
return icon;
}
protected void done(){
Icon icon= get();
lblImage.setIcon(icon); //lblImage可通过构造函数传入
}
}
testWorker.execute();
|
上述代码中,我们在按钮的事件处理函数中,创建了一个swingworker实例对象。调用构造函数时,指定第一个泛型参数为Icon,这是一个自定义类型,这里代表一个Icon图片对象。指定这一泛型参数,是为了指定doInBackground()方法的返回值,并在done()方法中获取。
doInBackground方法作为工作线程的一部分执行,它负责完成线程的基本任务,并以返回值来作为线程的执行结果。在doInBackground方法完成之后,SwingWorker调用done方法。如果任务需要在完成后,使用工作线程执行结果来更新GUI组件或者做些清理工作,可覆盖done方法来完成它们。使用SwingWorker的get方法可以获取doInBackground方法的结果,done方法是调用get方法的最好地方,因为此时已知道线程任务完成了,SwingWorker在EDT上激活done方法,因此可以在此方法内安全地和任何GUI组件交互。execute方法是异步执行,它立即返回到调用者。在execute方法执行后,EDT立即继续执行。
2.3 WebWorker vs SwingWorker
Swing Worker还有一些其他的方法,这里不再讨论。我们可以结合Web Worker,对比看看两者异同。
两者编程模型相同,都是在主线程中,将耗时工作交由工作线程去异步的完成,从而避免主线程的阻塞。
两者线程通信机制不同,Web Worker线程通信限制严格,仅能通过postMessage方法通信,而且参数传递均为值传递,没有引用传递;Swing Worker参数传递灵活,上述事例中,testWorker的doInBackground方法直接引用了strImageUrl变量,不过这一方式并不推荐,而是应当定义一个新类继承自SwingWorker,并在构造函数中传入imgUrl变量,然后在实例化worker线程中传入变量。
两者对UI界面的更新限制不同,Web Worker禁止在worker线程中操作dom元素,所以不能在worker中更新UI;Swing Worker允许在done方法中更新UI,这里并没有违背Swing的事件分发模型,因为最终还是在EDT上激活的done方法,依然遵循着事件分发模型。
3. Web Worker带来了什么
最后来总结Web Worker为javascript带来了什么,学习过程中,看到一些文章认为Web Worker为Javascript带来了多线程编程能力,我不认可这种观点。
3.1 Web Worker带来后台计算能力
Web Worker自身是由webkit多线程实现,但它并没有为Javasctipt语言带来多线程编程特性,我们现在仍然不能在Javascript代码中创建并管理一个线程,或者主动控制线程间的同步与锁等特性。
在我看来,Web Worker是worker编程模型在浏览器端Javascript语言中的应用。浏览器的运行时,同其他GUI程序类似,核心逻辑像是下面这个无限循环:
1
2
3
4
|
while(true){
1 更新数据和对象状态
2 渲染可视化UI
}
|
在Web Worker之前,Javascript执行引擎只能在一个单线程环境中完成这两项任务。而在其他典型GUI框架,如前文Swing库中,早已引入了Swing Worker来解决大量计算对UI渲染的阻塞问题。Web Worker的引入,是借鉴了worker编程模型,给单线程的Javascript带来了后台计算的能力。
3.2 Web Worker典型应用场景
既然Web Worker为浏览器端Javascript带来了后台计算能力,我们便可利用这一能力,将无限循环中第一项“更新数据和对象状态”的耗时部分交由Web Worker执行,提升页面性能。
部分典型的应用场景如下
1) 使用专用线程进行数学运算
Web Worker最简单的应用就是用来做后台计算,而这种计算并不会中断前台用户的操作
2) 图像处理
通过使用从<canvas>或者<video>元素中获取的数据,可以把图像分割成几个不同的区域并且把它们推送给并行的不同Workers来做计算
3) 大量数据的检索
当需要在调用 ajax后处理大量的数据,如果处理这些数据所需的时间长短非常重要,可以在Web Worker中来做这些,避免冻结UI线程。
4) 背景数据分析
由于在使用Web Worker的时候,我们有更多潜在的CPU可用时间,我们现在可以考虑一下JavaScript中的新应用场景。例如,我们可以想像在不影响UI体验的情况下实时处理用户输入。利用这样一种可能,我们可以想像一个像Word(Office Web Apps 套装)一样的应用:当用户打字时后台在词典中进行查找,帮助用户自动纠错等等。
Web Worker是什么的更多相关文章
- JavaScript多线程之HTML5 Web Worker
在博主的前些文章Promise的前世今生和妙用技巧和JavaScript单线程和浏览器事件循环简述中都曾提到了HTML5 Web Worker这一个概念.在JavaScript单线程和浏览器事件循环简 ...
- Web Worker javascript多线程编程(一)
什么是Web Worker? web worker 是运行在后台的 JavaScript,不占用浏览器自身线程,独立于其他脚本,可以提高应用的总体性能,并且提升用户体验. 一般来说Javascript ...
- Web Worker javascript多线程编程(二)
Web Worker javascript多线程编程(一)中提到有两种Web Worker:专用线程dedicated web worker,以及共享线程shared web worker.不过主要讲 ...
- 过段时间逐步使用HTML5新增的web worker等内容
想来快2017年了,2013年前的手机应该很少有人用了,以后逐渐使用HTML5新增的高级API吧. 先把web worker的内容再熟悉一下,因为微软虚拟学院的'面向有经验开发人员的 JavaScri ...
- web Worker使js实现‘多线程’?
大家都知道js是单线程的,在上一段js执行结束之前,后面的js绝对不会执行,那么为什么标题说js实现‘多线程’,虽然说加了引号,可是标题也不能乱写不是,可恶的标题党? 姑且抛开标题不说,先说我们经常会 ...
- HTML5:web socket 和 web worker
a:hover { cursor: pointer } 做练习遇到了一个选择题,是关于web worker的,问web worker会不会影响页面性能?补习功课之后,答案是不会影响. 查阅了相关资料学 ...
- javascript 多线程Web Worker不引用外部js文件的方法
最近在Android开发中 Webview通过调用JavascriptInterface的方式与App交互 在交互的过程中,有些App上的操作时间会比较长,Web中调用的话会造成程序假死的情况 于是想 ...
- HTML5 Web Worker的使用
Web Workers 是 HTML5 提供的一个javascript多线程解决方案,我们可以将一些大计算量的代码交由web Worker运行而不冻结用户界面. 一:如何使用Worker Web Wo ...
- Web Worker 是什么鬼?
前言 前端工程师们一定有过这样的体验,当一个页面加载了大量的 js 文件时,用户界面可能会短暂地"冻结".这很好理解,因为 js 是单线程的语言.我们再走的极端点,一段 js 中出 ...
- Web Worker
写在前面 众所周知,JavaScript是单线程的,JS和UI更新共享同一个进程的部分原因是它们之间互访频繁,但由于共享同一个进程也就会造成js代码在运行的时候用户点击界面元素而没有任何响应这样的情况 ...
随机推荐
- 分布式系统:CAP
一致不太理解CAP,最近好像有点感觉了,这里写下来,先介绍下CAP的定义: C:一致性.写完数据后,立马能看到最新数据. A:可用性.所有请求必须有响应. P:分区容错性.网络或服务器故障不会导致系统 ...
- 云服务器 ECS Linux 系统安装图形化桌面 (centos7 ubuntu14)
基于性能及通用性等因素,默认情况下,阿里云官方公共 Linux 系统镜像不会安装图形化桌面组件.本文简述了常用操作系统图形化桌面安装说明,您可以根据需求进行配置系统. 注意:图形化桌面可能会 显著降低 ...
- [Web 前端] 如何构建React+Mobx+Superagent的完整框架
ReactJS并不像angular一样是一个完整的前端框架,严格的说它只是一个UI框架,负责UI页面的展示,如果用通用的框架MVC来说,ReactJs只负责View了,而Angular则是一个完整的前 ...
- Eclipse 乱码 解决方案总结(UTF8 -- GBK)
UTF8 --> GBK; GBK --> UTF8 eclipse的中文乱码问题,一般不外乎是由操作系统平台编码的不一致导致,如Linux中默认的中文字体编码问UTF8, 而Wind ...
- [转]PHP用mysql数据库存储session
From : http://www.php100.com/html/webkaifa/PHP/PHPyingyong/2010/0226/4002.html 大部分使用php的人一旦应用到sessio ...
- git如何删除远端不存在的本地分支?
问题:远端分支删除后,如何删除之前拉取的本地分支? 答案: git fetch -p git remote show origin 可以查看remote地址,远程分支,还有本地分支与之相对应关系等信息 ...
- jpa命名规则 jpa使用sql语句 @Query
关键字方法命名sql where字句 AndfindByNameAndPwdwhere name= ? and pwd =? OrfindByNameOrSexwhere name= ? or sex ...
- 初识网络进程通信<Heart.X.Raid>
可以这样说:我们在网络上只做一件事,利用各种软件没完没了的相互通信. 对于单机系统而言,进程在系统中有自己唯一的进程号.但在网络环境下,各主机独立分配的进程号不能唯一标识该进程.例如,主机A赋于某进程 ...
- 【转】QT 串口QSerialPort + 解决接收数据不完整问题
类:QSerialPort 例程:Examples\Qt-5.9.1\serialport\terminal,该例子完美展示了qt串口收发过程,直接在这上面修改就可以得到自己的串口软件.核心方法 // ...
- C#与Visual Basic的异与同
C#是一种高级程序设计语言,是一种安全.稳定.简单.优雅的编程语言,它与Visual Basic有很多相同的地方,同时也有很多不同的地方.我们今天这篇博客本着学习C#的原则,着重介绍一下C#与Visu ...