html5 web worker学习笔记(记一)
(吐槽:浏览器js终于进入多线程时代!)
以前利用setTimeout、setInterval等方式的多线程,是伪多线程,本质上是一种在单线程中进行队列执行的方式。自从html5 web worker出现,js真正进入了多线程编程时期,现在就开始js的“真·多线程”秘籍修炼吧!
最近因为工作中的需要,使用了html5的web worker,之前一直对worker一知半解。直到看到IBM上的一篇博文(知识不是完全有效,可以当作参考),才对worker有了基本概念。
worker分类
worker分为专用线程和共享线程。专用线程只能在当前页面中访问到。而如果要多个页面访问同一个worker,就要使用共享线程,但前提是这几个页面是同域的。
worker基本用法
一、专用线程
1、在浏览器线程中(即插入页面的js代码,内联、外链的js代码都可以):
var worker=new Worker("testWorker.js");
worker.onmessage=function(event){
/*收到worker线程发送来的数据*/
console.log(event.data);
};
worker.onerror=function(event){
/*收到worker线程发送来的错误信息*/
console.log(event.data);
};
worker.postMessage("some data");/*向worker线程发送数据*/
worker一直处于监听状态,要释放这个线程必须在浏览器线程调用worker.terminate();以释放资源。
2、在worker线程代码中:
this.onmessage=function(event){
/*收到浏览器线程发来的信息,然后回复浏览器线程*/
this.postMessage("worker received data:"+event.data+"("+new Date()+")";
};
在worker线程中,如果不用接收浏览器线程发来数据或者浏览器线程不发送数据,则可以直接执行处理,最后this.postMessage(/*data*/)就行了。
在上例中,this指线程对象,所以最好的用法是在第一行代码的前面加上“var thread=this;”,然后就可以在任何地方使用thread.postMessage和thread.onmessage方法。worker线程中的代码变成:
var thread=this;
thread.onmessage=function(event){
/*收到浏览器线程发来的信息,然后回复浏览器线程*/
thread.postMessage("worker received data:"+event.data+"("+new Date()+")";
};
二、共享线程
1、浏览器线程中:
var sharedWorker=new SharedWorker("sharedWorker.js");
worker.onerror=function(e){
/*worker对象错误*/
console.log("create shared worker error.");
};
worker.port.onmessage=function(event){
console.log(event.data);
};
worker.port.onerror=function(e){
/*worker通信、worker线程中的错误*/
console.log(e.message);
};
worker.port.start();/*必须执行start以开始连接*/
在浏览器线程中,通信是通过worker的port对象进行的,每一个页面的port是不同的,具有唯一性。最关键的一点是start(),这个函数表示开始连接shared worker,连接成功时,worker线程将增加一个连接数。
在同域下的其他页面调用此shared worker,代码结构与此相同,只是处理数据的逻辑可能不同。
2、worker线程中:
var thread=this,
connectionCount=0;
thread.onconnect=function(e) {
/*有页面请求连接触发*/
var port=e.ports[0];/*获取指定页面的port,用这个port和页面通信*/
port.postMessage("new connection,index:"+connectionCount);
port.onmessage=function(event) {
port.postMessage("received data:"+event.data);
};
connectionCount++;
};
在worker代码中,在onconnect回调函数中获取请求连接者的连接对象port,然后就可以通过这个port与请求者通信。
在这里,可以把port缓存起来,以后worker可以随时主动postMessage给浏览器特定的页面线程。这需要页面发送自己的“全局唯一特征码”供worker识别。
生命周期
专用线程的生命周期与页面的生命周期一致,可以使用worker.terminate()关闭释放线程。
共享线程的生命周期与其连接数相关,当连接数为0时,将自动关闭释放。如果需要关闭当前页面的连接,可以调用worker.port.close(),worker线程中的连接数将减少一个。关闭页面也和调用worker.port.close具有同样的影响。
尾记
1、worker也和服务器端的多线程一样,创建、销毁开销较大。所以,worker只应该用于耗时操作,例如复杂、长时间的运算。
2、worker不能访问DOM及页面相关对象如window document,这也在一定程度上限制了worker的应用,也不能在worker中创建worker。
3、worker中可以使用XMLHttpRequest,可以自己写一个包装http请求的对象到worker线程代码中,或者找个开源的http库。使用开源库需要解决如何引入的问题,还没有研究。
4、可以动态创建worker代码。提供思路,具体怎么做的忘了:) ------------ 将需要运行的代码转换为字符串,再转换为二进制的Blob对象,再使用window.URL.createObjectURL创建动态url,参数是Blob对象,然后将这个动态url传入worker的构造函数,作为第一个参数。这种一般是用在专用线程上。例子如下。
var doWorkByHtml5Worker = (function () {
//使用html5的worker进行后台耗时耗Cpu计算
var worker, urlContext = window.URL || window.webkitURL || window.mozURL || window.msURL;
var blobBuilder, blobBuilderContext = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder;
if (blobBuilderContext) {
var clearBlob = function () {
blobBuilder = null;
blobBuilder = new blobBuilderContext();
blobBuilder.clear = clearBlob;
};
clearBlob();
} else if (Blob) {
blobBuilder = {
builder: null,
append: function (str) {
this.builder = new Blob([str]);
},
getBlob: function () {
return this.builder;
},
clear: function () {
this.builder = null;
}
}
}
return {
/*
* workFunc为需要运行的函数,可以是字符串,也可以是原型函数,如果是函数,将在内部转换为字符串。必须为函数形式。
* params为需要传入函数的参数
* callback为执行完毕的回调函数,参数为执行workFunc返回的值
*/
Do: function (workFunc, params, callback) {
var workStr = workFunc.toString();
if (workFunc !== workStr) {
workFunc = workStr;
}
blobBuilder.append('postMessage((' + workFunc.toString() + ')(' + JSON.stringify(params) + '));');
worker = new Worker(urlContext.createObjectURL(blobBuilder.getBlob()));
worker.onmessage = function (e) {
this.terminate();
worker = null;
blobBuilder.clear();
callback && callback(e.data);
};
}
};
})();
使用:
/*基本演示*/
doWorkByHtml5Worker.Do(
function(){
return "data from custom function";
},
null,
function(data){
/*回调*/
console.log(data);/*将打印字符串"data from custom function"*/
}
); /*带参数演示*/
doWorkByHtml5Worker.Do(
function(obj){
return "received object:{id:"+obj.id+",msg:\""+obj.msg+"\"}";
},
{id:0,msg:"go home"},
function(data){
/*回调*/
console.log(data);/*将打印字符串"received object:{id:0,msg:"go home"}"*/
}
); /*传入字符串型执行函数*/
var doSomething=(function(){
return "data from custom function";
}).toString();
/* 或者:var doSomething="function(){return \"data from custom function\";}";*/
doWorkByHtml5Worker.Do(
doSomething,
null,
function(data){
/*回调*/
console.log(data);/*将打印字符串"data from custom function"*/
}
);
参考:
1、菜鸟教程
2、IBM博文
3、W3C文档
html5 web worker学习笔记(记一)的更多相关文章
- 深入HTML5 Web Worker应用实践:多线程编程
HTML5 中工作线程(Web Worker)简介 至 2008 年 W3C 制定出第一个 HTML5 草案开始,HTML5 承载了越来越多崭新的特性和功能.它不但强化了 Web 系统或网页的表现性能 ...
- 深入 HTML5 Web Worker 应用实践:多线程编程
深入 HTML5 Web Worker 应用实践:多线程编程 HTML5 中工作线程(Web Worker)简介 至 2008 年 W3C 制定出第一个 HTML5 草案开始,HTML5 承载了越来越 ...
- JavaScript多线程之HTML5 Web Worker
在博主的前些文章Promise的前世今生和妙用技巧和JavaScript单线程和浏览器事件循环简述中都曾提到了HTML5 Web Worker这一个概念.在JavaScript单线程和浏览器事件循环简 ...
- 【前端】移动端Web开发学习笔记【2】 & flex布局
上一篇:移动端Web开发学习笔记[1] meta标签 width设置的是layout viewport 的宽度 initial-scale=1.0 自带 width=device-width 最佳实践 ...
- 【前端】移动端Web开发学习笔记【1】
下一篇:移动端Web开发学习笔记[2] Part 1: 两篇重要的博客 有两篇翻译过来的博客值得一看: 两个viewport的故事(第一部分) 两个viewport的故事(第二部分) 这两篇博客探讨了 ...
- 【前端】Web前端学习笔记【2】
[2016.02.22至今]的学习笔记. 相关博客: Web前端学习笔记[1] 1. this在 JavaScript 中主要有以下五种使用场景 在全局函数调用中,this 绑定全局对象,浏览器环境全 ...
- 【前端】Web前端学习笔记【1】
... [2015.12.02-2016.02.22]期间的学习笔记. 相关博客: Web前端学习笔记[2] 1. JS中的: (1)continue 语句 (带有或不带标签引用)只能用在循环中. ( ...
- ASP.NET MVC Web API 学习笔记---第一个Web API程序
http://www.cnblogs.com/qingyuan/archive/2012/10/12/2720824.html GetListAll /api/Contact GetListBySex ...
- Web前端学习笔记(001)
....编号 ........类别 ............条目 ................明细....................时间 一.Web前端学习笔记 ...
随机推荐
- PAT 1102 Invert a Binary Tree
The following is from Max Howell @twitter: Google: 90% of our engineers use the software you wrote ( ...
- Ch’s gift
Ch’s gift Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) Proble ...
- noip模拟赛 逃避
题目描述 给定一篇只含有大小写字母,空格以及 ′.′(不含引号)的长度为 L 的文章.文章被若干个 ′.′ 划分 成若干个句子,句子被若干个空格划分成单词.你需要将文章中每个句子第一个单词的首字母改成 ...
- hdu 4171 最短路
#include<stdio.h> #include<string.h> #include<queue> #include<iostream> usin ...
- pandas中选取某行为缺失值的数据,并返回
1.df.dropna() 可以返回去掉NaN的df结果集. 2.pandas中dataframe取差集: df=pd.DataFrame({"name":[1,2,3,np.Na ...
- JAVA的堆和栈(转)
堆栈是 两种数据结构.堆栈都是一种数据项按序排列的数据结构,只能在一端(称为栈顶(top))对数据项进行插入和删除.在单片机应用中,堆栈是个特殊的存储 区,主要功能是暂时存放数据和地址,通常用来保护断 ...
- 2015 Changchun Regional
弱没机会去长春,但拿了题来做了,加上请教各路大牛,理论AC了一发,但没实现~(感谢各路有形无形的大牛的指导) A题~Too Rich 给你1,5,10,20,50,100,200,500,1000,2 ...
- [Android L or M ]解除SwitchPreference与Preference的绑定事件
需求描写叙述 默认情况,Android的两个控件SwitchPreference和CheckBoxPreference的事件处理是和Preference整个区域的事件绑定在一起的,然而,有时须要将其事 ...
- 《解读window核心编程》 之 注冊表
1 注冊表的作用及组织形式 Windows系统使用注冊表来存储系统和应用程序配置数据.非常多系统和应用程序重要的配置的信息都存储在注冊表中. 注冊表是一种以树型结构组织的数据库.树的每个节点称 作键( ...
- 学习笔记—— 一些UPDATE语句
UPDATE语句原来还有许多种写法,有的还很复杂,孤陋寡闻的我甚至闻所未闻.幸甚至哉,记而志之. 0.UPDATE 表名 SET 字段... FROM ...的方式 USE AdventureWork ...