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前端学习笔记 ...
随机推荐
- Spring整合Junit框架进行单元测试Demo
一.开发环境 eclipse版本:4.6.1 maven版本:3.3.3 junit版本:4.12 spring版本:4.1.5.RELEASE JDK版本:1.8.0_111 二.项目结构 图 三. ...
- 【Codeforces 474D】Flowers
[链接] 我是链接,点我呀:) [题意] 让你吃东西 B食物一次必须要吃连续k个 但是对A食物没有要求 问你有多少种吃n个食物的方法(吃的序列) [题解] 设f[i]表示长度为i的吃的序列且符合要求的 ...
- hdu_1009_FatMouse' Trade_201310280910
FatMouse' Trade http://acm.hdu.edu.cn/showproblem.php?pid=1009 Time Limit: 2000/1000 MS (Java/Others ...
- kendo Grid json解析的问题
新建立了一个 页面,在grid中使用了dropdownlist,总是显示companyId is not defined ,以前这个问题解决过了,忘记记录了额,现在不知道怎么办了 下面的这个解决方法是 ...
- github在README中展示demo
2017年更新,现在github再master分支直接就可以操作,所以我改了这篇文章 问题所在? 解决办法? 博主建议? 一:问题的所在 相信很多小胖友们在把自己的网页上传到github仓库中,都 ...
- [转]十五天精通WCF——第十天 学会用SvcConfigEditor来简化配置
我们在玩wcf项目的时候,都是自己手工编写system.serviceModel下面的配置,虽然在webconfig中做wcf的服务配置的时候,vs提供大多 数的代码提示,但对于不太熟悉服务配置的小鸟 ...
- post and get
POST和GET是Web编程中的两个术语,他们是通过URI访问resource的两种方式.简单的说, GET 是把要访问的资源嵌入在URI中. 假设你在一个页面 http://www.myphone. ...
- web项目log日志查看分析->流程理解
1.DEBUG [2017-07-10 11:38:41,705][] org.springframework.web.servlet.DispatcherServlet:865 - Dispatch ...
- Android平台Airplay的实现方法
Airplay属于局域网内异构设备之间分享多媒体数据的一种通信协议.Airplay设备有客户端和服务器之分,一般将小屏IOS设备实现为Airplay客户端,大屏幕设备实现为Airplay服务器.即iP ...
- Mybatis+0+null,小问题引发的血案
Mybatis在进行<if test="status != null and status != ''">判空操作时,假设status为0的时候,该推断条件的值为fal ...