关于Web Worker你必须知道的7件事
介绍
通过使用Web Worker, 我们可以在浏览器后台运行Javascript, 而不占用浏览器自身线程。Web Worker可以提高应用的总体性能,并且提升用户体验。如果你想在自己的Web应用中使用Web Worker, 不妨来了解一下有关Web Worker的7件事。
1. Web Worker 可以让你在后台运行Javascript
一般来说Javascript和页面的UI会共用一个线程,所以当点击一个按钮开始运行Javascript后,在这段代码运行完毕之前,页面是无法响应用户操作的,换句话来说就是被“冻结”了。而这段代码可以交给Web Worker在后台运行,那么页面在Javascript运行期间依然可以响应用户操作。后台会启动一个worker线程来执行这段代码,用户可以创建多个worker线程。所以你可以在前台做一些小规模分布式计算之类的工作,不过Web Worker有以下一些使用限制:
- Web Worker无法访问DOM节点;
- Web Worker无法访问全局变量或是全局函数;
- Web Worker无法调用alert()或者confirm之类的函数;
- Web Worker无法访问window、document之类的浏览器全局变量;
不过Web Worker中的Javascript依然可以使用setTimeout(),setInterval()之类的函数,也可以使用XMLHttpRequest对象来做Ajax通信。
2. 有两种Web Worker
Web workers可分为两种类型:专用线程dedicated web worker,以及共享线程shared web worker。 Dedicated web worker随当前页面的关闭而结束;这意味着Dedicated web worker只能被创建它的页面访问。与之相对应的Shared web worker可以被多个页面访问。在Javascript代码中,“Work”类型代表Dedicated web worker,而“SharedWorker”类型代表Shared web worker。
在绝大多数情况下,使用Dedicated web worker就足够了,因为一般来说在web worker中运行的代码是专为当前页面服务的。而在一些特定情况下,web worker可能运行的是更为普遍性的代码,可以为多个页面服务。在这种情况下,我们会创建一个共享线程的Shared web worker,它可以被与之相关联的多个页面访问,只有当所有关联的的页面都关闭的时候,该Shared web worker才会结束。相对Dedicated web worker,shared web worker稍微复杂些。
3. “Worker”对象代表Dedicated Web Worker
现在来看如何使用Dedicated web worker。下面的例子中用到了jQuery以及Modernizr作为Javascript库,然后往HTML页面中加入以下代码:
- <!DOCTYPE html>
- <html>
- <head>
- <title></title>
- <script type="text/javascript" src="script/modernizr.js"></script>
- <script type="text/javascript" src="script/jquery-2.0.0.js"></script>
- <script type="text/javascript">
- $(document).ready(function(){
- if(!Modernizr.webworker){
- alert("This browser doesn't support Web Worker!");
- return;
- }
- $("#btnStart").click(function(){
- var worker = new Worker("script/lengthytask.js");
- worker.addEventListener("message", function(evt){
- alert(evt.data);
- }, false);
- worker.postMessage(10000)
- });
- });
- </script>
- </head>
- <body>
- <form>
- <input type="button" id="btnStart" value="Start Processing"/>
- </form>
- </body>
- </html>
这个HTML页面中有个按钮,点击后会运行一个Javascript文件。上面的代码中首先检测当前浏览器是否支持Web Worker,不支持的话,就跳出提醒信息。
按钮的点击事件中创建了Worker对象,并给它指定了Javascript脚本文件——lengthytask.js(稍后会有代码),并且给Worker对象绑定了一个“message”事件。该事件会在后台代码(lengthytask.js)向页面返回数据时触发。“message”事件可以通过event.data来获取后台代码传回的数据。最后,postMessage方法正式执行lengthytask.js,该方法还可以向后台代码传递参数, 后台代码同样通过message事件获取该参数。
下面是lengthytask.js主要包含的代码:
- addEventListener("message", function(evt){
- var date = new Date();
- var currentDate = null;
- do {
- currentDate = new Date();
- }while(currentDate - date < evt.data);
- postMessage(currentDate);
- }, false);
以上代码在后台监听message时间,并获取页面传来的参数:10000;这里实际上是一个计时函数:在message事件被触发10000毫秒之后,把结果(currentDate)传给页面。
所以当点击“Start Processing”按钮,页面会在10秒钟后把当时的时刻alert出来。在这10秒钟内页面依然可以响应鼠标键盘事件。
4. “SharedWorker”对象代表Shared Web Worker
前面的代码使用的是dedicated web worker。 这一节会用shared web worker代替dedicated web worker,来区别两者的不同。下面是同一个例子的shared web worker版本:
- addEventListener("message", function(evt){
- var date = new Date();
- var currentDate = null;
- do {
- currentDate = new Date();
- }while(currentDate - date < evt.data);
- postMessage(currentDate);
- }, false);
请注意加黑的代码,这里创建了一个SharedWorker对象,并把message事件绑定在shared worker的port对象上;同样由port对象发起postMessage, 开始执行后台代码sharedlengthytask.js。
下面是sharedlengthytask.js的主要代码:
- var port;
- addEventListener("connect", function(evt){
- port = evt.ports[0];
- port.addEventListener("message", function(evt){
- var date = new Date();
- var currentDate = null;
- do {
- currentDate = new Date();
- }while(currentDate - date < evt.data);
- port.postMessage(currentDate);
- }, false);
- port.start();
- }, false);
使用SharedWorker对象的后台代码需要绑定connect和message事件, connect事件会在页面上的port被start时触发。之后的message事件的回调函数与之前的基本相同,最后port调用postMessage方法把结果传回给页面。
5. Web Worker使用XMLHttpRequest与服务端通信
有些情况下,web worker还需要与服务器进行交互。比如页面可能需要处理来自数据库中的信息,我们就需要使用Ajax技术与服务器交互,下面代码包含了web worker如何从服务端获取数据:
- addEventListener("message", function(evt){
- var xhr = new XMLHttpRequest();
- xhr.open("GET", "lengthytaskhandler.ashx");
- xhr.onload = function(){
- postMessage(xhr.responseText);
- };
- xhr.send();
- },false);
上面的代码向服务端的asp.net服务lengthytaskhandler.ashx发出GET请求。并注册了获取数据后的onload事件。下面的代码是服务端的lengthytaskhandler.ashx:
- namespace WebWorkerDemo
- {
- public class LengthyTaskHandler:IHttpHandler
- {
- public void ProcessRequest(HttpContext context)
- {
- System.Threading.Thread.Sleep(10000);
- context.Response.ContentType = "text/plain";
- content.Response.Write("Processing successful!");
- }
- public bool IsReusable
- {
- get
- {
- return false;
- }
- }
- }
- }
如你所见,ProcessRequest模拟了一个长时间运行的任务,并返回了“Processing successful!”的消息。
6. 通过Error事件捕捉错误信息
当我们把越来越复杂的逻辑加到Web Worker里时,错误处理机制是必不可少的。而Web Worker恰恰提供了error事件,供开发者捕捉错误信息。下面的代码展示了如何绑定error事件:
- $("#btnStart").click(function(){
- var worker = new Worker("scripts/lengthytask.js");
- worker.addEventListener("error", function(evt){
- alert("Line #" + evt.lineno + " - " + evt.message + " in " + evt.filename);
- }, false);
- worker.postMessage(10000);
- });
如上可见, Worker对象可以绑定error事件;而且evt对象中包含错误所在的代码文件(evt.filename)、错误所在的代码行数(evt.lineno)、以及错误信息(evt.message)。
7. 通过terminate()方法终止Web Worker
有些情况下,我们可能需要强制终止执行中的Web Worker。Worker对象提供了terminate()来终止自身执行任务,被终止的Worker对象不能被重启或重用,我们只能新建另一个Worker实例来执行新的任务。
总结
Web Worker可以在后台执行脚本,而不会阻塞页面交互。Worker对象分为两种:专用式Web Worker和共享式Web Worker:专用式的Web Worker只能被当个页面使用,而共享式的Web Worker可以在被多个页面使用。另外,本文还介绍了Web Worker的错误处理机制,以及使用Ajax与服务端交互。
关于Web Worker你必须知道的7件事的更多相关文章
- 每一位想有所成就的程序员都必须知道的15件事(走不一样的路,要去做,实践实践再实践,推销自己,关注市场)good
从 为之漫笔作者:为之漫笔 有超过 100 人喜欢此条目 原文地址:How to advance your career? Read the Passionate Programmer! 我刚看完Ch ...
- 关于DevOps你必须知道的11件事
转自:http://www.infoq.com/cn/articles/11devops 关于作者 Gene Kim在多个角色上屡获殊荣:CTO.研究者和作家.他曾是Tripwire的创始人并担任了1 ...
- 从Oracle迁移到Mysql之前必须知道的50件事
1. 对子查询的优化表现不佳. 2. 对复杂查询的处理较弱 3. 查询优化器不够成熟 4. 性能优化工具与度量信息不足 5. 审计功能相对较弱 6. 安全功能不成熟,甚至可以说很粗糙.没有用户组与角色 ...
- Java中的集合-您必须知道的13件事
Java Collections Framework是Java编程语言的核心部分之一.集合几乎用于任何编程语言中.大多数编程语言都支持各种类型的集合,例如List, Set, Queue, Stack ...
- 每一个C#开发者必须知道的13件事情
1.开发流程 程序的Bug与瑕疵往往出现于开发流程当中.只要对工具善加利用,就有助于在你发布程序之前便将问题发现,或避开这些问题. 标准化代码书写 标准化代码书写可以使代码更加易于维护,尤其是在代码由 ...
- C#开发者必须知道的13件事情
1.开发流程 程序的Bug与瑕疵往往出现于开发流程当中.只要对工具善加利用,就有助于在你发布程序之前便将问题发现,或避开这些问题. 标准化代码书写 标准化代码书写可以使代码更加易于维护,尤其是在代码由 ...
- 初学JavaScript须知道的七件事
1.1.缩略标记 //定义对象 //var car = new Object(); //car.colour = 'red'; //car.wheels = 4; //car.hubcaps = 's ...
- C#刨根究底:《你必须知道的.NET》读书笔记系列
一.此书到底何方神圣? <你必须知道的.NET>来自于微软MVP—王涛(网名:AnyTao,博客园大牛之一,其博客地址为:http://anytao.cnblogs.com/)的最新技术心 ...
- 转15个必须知道的chrome开发者技巧GIF
在Web开发者中,Google Chrome是使用最广泛的浏览器.六周一次的发布周期和一套强大的不断扩大开发功能,使其成为了web开发者必备的工具.你可能已经熟悉了它的部分功能,如使用console和 ...
随机推荐
- Android计时器实例
布局文件 <Chronometer android:id="@+id/chronometer" android:layout_width="wrap_content ...
- TCP/IP协议原理【转载】
前述 各种L2数据网具有不同的通信协议与帧结构,其网络节点设备可以是各种类型的数据交换机(X.25.FR.Ethernet和ATM等分组交换机):而L3数据网(IP网或internet) ...
- Ubuntu上如何安装Java,Eclipse,Pydev,Python(自带,不用装),BeautifulSoup
如何安装Java,如果出于编程的需要安装Java,需要安装的是JDK,而不仅仅是JRE,下面说说如何在Ubuntu下如何安装JDK:只有两步,1.下载并解压,2.配置环境变量1.下载并解压:下载地址: ...
- php面向对象_get(),_set()的用法
一般来说,总是把类的属性定义为private,这更符合现实的逻辑.但是,对属性的读取和赋值操作是非常频繁的,因此在PHP5中,预定义了两个函数“__get()”和“__set()”来获取和赋值其属性, ...
- PHP 遍历目录
$dir = $_SERVER['DOCUMENT_ROOT'].'/test'; //var_dump($dir);exit; function my_scandir($dir) { $files ...
- c++ const总结
[本文链接] http://www.cnblogs.com/hellogiser/p/cplusplus-const-summay.html 看到const 关键字,C++程序员首先想到的可能是con ...
- 【python】Python标准库defaultdict模块
来源:http://www.ynpxrz.com/n1031711c2023.aspx Python标准库中collections对集合类型的数据结构进行了很多拓展操作,这些操作在我们使用集合的时候会 ...
- [Android Pro] Android签名与认证详细分析之一(CERT.RSA剖析)
转载自:http://www.thinksaas.cn/group/topic/335450/ 一.Android签名概述 我们已经知道的是:Android对每一个Apk文件都会进行签名,在Apk文件 ...
- Myeclipse 安装svn插件
安装subclipse, SVN插件1.从官网下载site-1.8.22.zip文件 访问不了可点我网盘2.从中解压出features与 plugins文件夹,复制到MyEclipse\MyEcl ...
- cVim—Chrome上更强大的vim插件
cVim——Chrome上更强大的vim插件 介绍 也许很多人在chrome上都用过类似Vimium, ViChrome的插件,这些插件的目的都差不多,就是在浏览器中提供一些类似vim的操作来提高效率 ...