HTML5新特性之Web Worker
1、概述
JavaScript语言采用的是单线程模型,也就是说,所有任务排成一个队列,一次只能做一件事。随着电脑计算能力的增强,这一点带来很大的不便,无法充分发挥JavaScript的潜能。龙其考虑到,File API允许JavaScript读取本地文件,就更加如此了。
Web Worker的目就,就是为JavaScript创造多线程环境,允许主线程将一些任务分配给子线程。在主线程运行的同时,子线程在后台运行,两者互不干扰。等到子线程完成计算任务,再把结果返回给主线程。因此,每一个子线程就好像一个“工人”(worker),默默地完成自己的工作。
Web Worker有以下几个特点:
- 同域限制:子线程加载的脚本文件,必须与主线程的脚本文件在同一个域。
- DOM限制:子线程无法读限网页的DOM对象,即document、window、parent这些对象,子线程都无法得到。(但是,navigator对象和location对象可以获得。)
- 脚本限制:子线程无法读取网页的全局变量和函数,也不能执行alert和confirm方法,不过可以执行setInterval和setTimeout,以及使用XMLHttpRequest对象发出AJAX请求。
- 文件限制:子线程无法读取本地文件,即子线程无法打开本机的文件系统(file://),它所加载的脚本,必须来自网络。
使用之前,检查浏览器是否支持这个API。支持的浏览器包括 IE 10+、Firefox 3.6+、Safari 4.0+、Chrome 和 Opera 11,但是手机浏览器还不支持。
if (window.Worker) {
// 支持
} else {
// 不支持
}
2、新建和启动子线程
在主线程内部,采用new命令调用Worker方法,可以新建一个子线程。
var worker = new Worker('work.js');
Worker方法的参数是一个脚本文件,这个文件就是子线程所要完成的任务,上面代码中是work.js。由于子线程不能读取本地文件系统,所以这个脚本文件必须来自网络端。如果下载没有成功,比如出现404错误,这个子线程就会默默地失败。
子线程新建之后,并没有启动,必需等待主线程调用postMessage方法,即发出信号之后才会启动。
worker.postMessage('hello world');
postMessage方法的参数,就是主线程传给子线程的信号。它即可以是一个字符串,也可以是一个对象。
worker.postMessage({method: 'each', args: ['work']});
3、子线程的事件监听
在子线程内,必须有一个回调函数,监听message事件。
//File: work.js self.addEventListener('message', function(e) { self.postMessage('You said: ' + e.data); }, false);
self代表子线程自身,self.addEventListener表示对子线程的message事件指定回调函数(直接指定onmessage属性的值也可以)。回调函数的参数是一个事件对象,它的data属性包含主线程发来的信号。self.postMessage则表示,子线程向主线程发送一个信号。
根据主线程发来的不同的信号值,子线程可以调用不同的方法。
// File: work.js self.addEventListener('message', function(e) {
var method = e.data.method;
var args = e.data.args;
var reply = doSomething(args);
self.postMessage({method: method, reply: reply});
}, false);
4、主线程的事件监听
主线程也必须指定message事件的回调函数,监听子线程发来的信号。
// File: main.js
worker.addEventListener('message', function(e) {
console.log(e.data);
}, false);
5、错误处理
主线程可以监听子线程是否发生错误。如果发生错误,会触发主线程的error事件。
worker.onerror(function(e) {
console.log(e);
}); // or
worker.addEventListener('error', function(e) {
console.log(e);
}, false);
6、关闭子线程
使用完毕后,为了节省系统资源,我们必须在主线程调用terminate方法,手动关闭子线程。
worker.terminate();
也可以子线程内部关闭自身。
self.close();
7、主线程与子线程的数据通信
主线程与子线程之间的通信内容,可以是文本,也可以是对象。需要注意的是,这种通信是拷贝关系,即是传值而不是传址,子线程对通信内容的修改,不会影响到主线程。事实上,浏览器内部的运行机制是,先将通信内容串行化,然后把串行化后的字符串发给子线程,后者再将它还原。
主线程也子线程这间也可以交换二进制数据,比如File、Blob、ArrayBuffer等对象,也可以在线程之间发送。
但是,用拷贝方式发送二进制数据,会造成性能问题。比如,主线程向子线程发送一个500MB文件,默认情况下浏览器会生成一个原文件的拷贝。为了解决这个问题,JavaScript允许主线程把二进制数据直接转移给子线程,但是一旦转移,主线程就无法再使用这些二进制数据了,这是为了防止出现多个线程同时修改数据的麻烦局面。这种转移数据的方法,叫做Transferable Objects。
如果要使用该方法,postMessage方法的最后一个参数必须是一个数组,用来指定前面发送的哪些值可以被转移给子线程。
worker.postMessage(arrayBuffer, [arrayBuffer]);
8、同页面的Web Worker
通常情况下,子线程载入的是一个单独的JavaScript文件,但是也可以载入与主线程在同一个网页的代码。假设网页代码如下:
<!DOCTYPE html>
<body>
<script id="worker" type="app/worker"> addEventListener('message', function() {
postMessage('Im reading Tech.pro');
}, false);
</script>
</body>
</html>
我们可以读取页面的script,用worker来处理。
var blob = new Blob([document.querySelector('#workere').textContent]);
这里需要把代码当作二进制数据读取,所以使用Blob接口。然后,这个二进制对象转为URL,再通过这个URL创建worker。
var url = window.URL.createObjectURL(blob); var worker = new Worker(url);
部署事件监听代码。
worker.addEventListener('message', function(e) {
console.log(e.data);
}, false);
最后启动worker。
worker.postMessage('');
整个页面的代码如下:
<!DOCTYPE html>
<body>
<script id="worker" type="app/worker"> addEventListener('message', function() {
postMessage('Work done!');
}, false); </script> <script>
(function() { var blob = new Blob([document.querySelector('#worker').textContent]); var url = window.URL.createObjectURL(blob); var worker = new Worker(url); worker.addEventListener('message', function(e) {
console.log(e.data);
}, false); worker.postMessage('');
})();
</script>
</body>
</html>
可以看到,主线程和子线程的代码都在同一个网页上面。
上面所讲的Web Worker都是专属于某个网页的,当该网页关闭,worker就自动结束。除此之外,还有一种共享式的Web Worker,允许多个浏览器窗口共享同一个worker,只有当所有窗口关闭,它才会结束。这种共享式的Worker用SharedWorker对象来创建,因为适用场合不多,这里就省略了。
9、参考链接
[1] Matt West, Using Web Worker to Speed-Up Your JavaScript Applications
[2] Eric Bidelman, The Basics of Web Workers
[3] Eric Bidelman, Transferable Objects: Lightning Fast!
[4] Jesse Cravens, Web Worker Patterns
[5] Bipin Joshi, 7 Things You Need To Know About Web Workers
[6] ruanyf, Web Worker
HTML5新特性之Web Worker的更多相关文章
- HTML5 十大新特性(八)——Web Worker
由于js是单线程的,所以H5添加了这个叫做webWorker的概念,允许js创建多个线程,但是子线程完全受主线程控制,且不能操作DOM,从而来处理一些比较耗时的操作. 那么如何创建一个子线程呢?通过这 ...
- HTML5新特性-多线程(Worker SharedWorker)
There is no doubt that JavaScript是没有多线程之说的,他只能一件事一件事的做,做完一件事再做下一件事,假如你的js要花一段比较长的时间做一件事的话,那么浏览器将会卡顿一 ...
- web全栈架构师[笔记] — 03 html5新特性
HTML5新特性 一.geolocation PC端 精度比较低 通过IP库定位 移动端 通过GPS window.navigator.geolocation 单次 getCurrentPositio ...
- html5新特性
这一篇博文不会告诉你怎么去使用html5的新特性,只会给你总结一下新特性------对于好学的人可以把这篇文章当做一个目录 对于初接触的人来说是一个导向 对于已经接触过的人来说是一个检测你掌握程度的检 ...
- html5新特性与用法大全了解一下
有好多小伙伴私聊我问我html5新特性 和用法,下面我给大家具体介绍一下html5都新加了哪些新特性,下面我给大家总结一下. 1)新的语义标签 footer header 等等2)增强型表单 表单2. ...
- HTML5新特性--svg-echarts(重点)-拖动API-WebWorker
一.html5新特性--svg--(折线/渐变特效对象/滤镜) #折线:多个坐标点组件一条折线 <polyline points="50,50 70,55 60,66 " s ...
- HTML5新特性之CSS+HTML5实例
1.新的DOCTYPE和字符集 HTML5的一项准则就是化繁为简,Web页面的DOCTYPE被极大的简化. <!DOCTYPE html> 同时字符集声明也被简化了: <meta c ...
- HTML5新特性:范围样式
原文出处:http://blog.csdn.net/hfahe/article/details/7381141 Chromium 最近实现了一个HTML5的新特性:范围样式,又叫做< ...
- 前端进阶系列(三):HTML5新特性
HTML5 是对 HTML 标准的第五次修订.其主要的目标是将互联网语义化,以便更好地被人类和机器阅读,并同时提供更好地支持各种媒体的嵌入.HTML5 的语法是向后兼容的.现在国内普遍说的 H5 是包 ...
随机推荐
- Dynamic CRM 2013学习笔记(四十六)简单审批流的实现
前面介绍过自定义审批流: Dynamic CRM 2013学习笔记(十九)自定义审批流1 - 效果演示 Dynamic CRM 2013学习笔记(二十一)自定义审批流2 - 配置按钮 Dynamic ...
- HTML 中禁用鼠标右键和不能选中文字
在body中加这句就可以了. <body oncontextmenu="return false" onselectstart="return false" ...
- 使用gdb调试Python进程
使用gdb调试Python进程 有时我们会想调试一个正在运行的Python进程,或者一个Python进程的coredump.例如现在遇到一个mod_wsgi的进程僵死了,不接受请求,想看看究竟是运行到 ...
- 为什么说外卖O2O行业的未来在于尖端技术?
7月13日,百度公司董事长兼CEO李彦宏在发布会上谈及百度外卖时表示,百度外卖里有非常多的人工智能技术的应用,比如同样的商家订单,先配送后配送,时间路线规划等等,都有人工智能的技术,涉及机器学习的问题 ...
- 共享jQuery/Eclipse/SVN/PS/DW/的API文档
1:jQuery的API和jquery.js和jquery.min.js 链接:http://pan.baidu.com/s/1gf7GD83 密码:tbt1 2:虚拟机软件和frdora和ubunt ...
- 【关于新版Cocos2dx/Cocos2d-JS】安装包和使用方式的变化
最近有读者反馈说,最新的Cocos2dx或者说2d-JS下载之后跟书本说的安装方式相差很大. 刚下载最新版3.9试了一下,其实用法还是没有变的. 新版把cocos2dx和cocos2d-js合并了,这 ...
- javaweb回顾第四篇Servlet异常处理
前言:很多网站为了给用户很好的用户体验性,都会提供比较友好的异常界面,现在我们在来回顾一下Servlet中如何进行异常处理的. 1:声明式异常处理 什么是声明式:就是在web.xml中声明对各种异常的 ...
- "Cannot find one of more components. Please reinstall the application"--安装VS2013之后不能正常打开的处理办法
今天,安装完VS2013之后,不能正常启动.总提示一个让人摸不到头脑的错误: "Cannot find one of more components. Please reinstall th ...
- C# Bitmap类型与Byte[]类型相互转化
Bitmap => byte[] Bitmap b = new Bitmap( "test.bmp "); MemoryStream ms = new Memory ...
- 原创内容搬家到csdn博客啦~
以后原创的文章就发布在csdn博客啦: http://blog.csdn.net/aceyan0718 这里就用来当作一个网络笔记本吧,转载些优质的内容