因为下个项目中要用到一些倒计时的功能,所以就提前准备了一下,省的到时候出现一下界面不友好和一些其他的事情。正好趁着这个机会也加深一下html5中的多线程worker的用法和理解。

Worker简介

JavaScript 语言采用的是单线程模型,也就是说,所有任务只能在一个线程上完成,一次只能做一件事。前面的任务没做完,后面的任务只能等着。这些都是我们所公知的。但是随着业务的不断增加,只是单纯的单线程模式已经可能无法满足我们的需求了。于是在html5中新增了后台任务worker API。

w3c中的介绍:web worker 是运行在后台的 JavaScript,独立于其他脚本,不会影响页面的性能。您可以继续做任何愿意做的事情:点击、选取内容等等,而此时 web worker 在后台运行。

worker就是为了JavaScript 创造多线程环境,允许主线程创建 Worker 线程,将一些任务分配给后者运行。开启后台线程,在不影响前台线程的前提下做一些耗时或者异步的操作。因为是不同的线程,所以主线程与worker线程互不干扰。也不会相互打断。所以在一些场景可以提高页面的流程性。Worker 线程一旦新建成功,就会始终运行,不会被主线程上的活动(比如用户点击按钮、提交表单)打断。这样有利于随时响应主线程的通信。但是,这也造成了 Worker 比较耗费资源,不应该过度使用,而且一旦使用完毕,就应该关闭。

使用规则

  1. 必须同源:也就是说js文件的路径必须和主线程的脚本同源。防止了外部引用。
  2. dom限制:在worker线程中不能操作dom(document,window,parent)。注意可以使用浏览器的navigator和location对象。
  3. 通讯限制:worker线程和主线程不在一个上下文中所以不能直接通讯。也就是说主线程定义的变量在worker中也是不能使用的。所有只能通过消息完成。
  4. 提示禁止:worker线程不能alert和confirm,这个不知到具体原因?
  5. 传值dom:进行消息通讯也不能传值dom只能是变量。
  6. ie限制:ie9不能使用!ie9不能使用!ie9不能使用!

worker文档

Web Workers API的Worker界面代表了一个可以轻松创建的后台任务,可以将消息发送回其创建者。创建worker就像调用 构造函数并指定要在工作线程中运行的脚本一样简单。

构造函数

worker():创建一个专用的Web worker,在指定的URL上执行脚本。示例:var worker=new Worker('js/setTime.js');

属性

onerror:

这是一个在error事件发生时调用的函数,并且通过该函数冒泡worker。示例:worker.onerror=function(){....};

onmessage:

这是一个worker中message事件要发生的时候调用的事件。  示例:worker.onmessage=function(){....};

这个事件一般与postMessage事件同时使用,一个用来发送数据,一个用来接受数据。例如:

主线程中:

  var jsId = "00001";
var worker = new Worker('js/setTime.js');
worker.postMessage(jsId);

worker线程中:

//接受事件参数
onmessage = function(e) { console.log(e.data[0])
}

这样就完成了一个主线程向worker线程传递参数的过程。同样如果worker线程要向主线程传递参数反过来写即可。

onmessageerror:

在消息传递过程出现错误的属性事件。示例:worker.onmessageerror=function(){....};

方法

postMessage:

向线程worker的内部范围发送消息,可以设置参数,发送给worker线程的数据。在onmessage中接受。

terminate:

过多的开启worker线程非常浪费资源所以在使用过后可以终止它,终止方法使用terminate()。示例:worker.terminate();

close:

除了上面的关闭,如果是在worker线程自身也可以使用self.close()关闭。

计时器示例

上面说了那么多都是介绍worker的一些基本属性或者方法的使用。下面通过具体的示例来看效果。

我们就拿最常用的倒计时来做示例说明。很简单的一个例子。我们在业务中经常遇到倒计时业务,在倒计时的时候还要做一些其他的业务。因为js单线程的特性,你会发现你的倒计时在你进行其他业务操作的时候是暂停了的。例如现在是9:57你进行了三秒的业务处理。等业务处理完成应该是:9:54,但是你的倒计时还是9:57.就很明显的说明了这一个现象。

场景业务设计

那么我们现在设计这么一个业务操作,

  • 首先我们页面有一个定时器和一个业务操作按钮(用来模拟耗时的操作)。
  • 然后把定时器写到一个worker中进行倒计时操作。
  • 最后通过消息通讯把每次的倒计时时间发送给主线程让主线程修改显示时间。
  • 结束倒计时完毕结束定时器和线程

有人可能会说为什么还要回到主线程修改时间显示值,请看一下上面的使用规则,我本来也是打算进行主线程传值dom给worker线程奈何不行只能在回传回来。

代码展示

Html代码:

<body>
<div>
<span id="Minute_p">10</span> :
<span id="Second_p">00</span>
</div> <button type="button" onclick="business()">耗时操作</button>
</body>

主线程js代码:

            //页面加载完成后初始化
window.onload = function() {
//创建定时器线程
var worker = new Worker('js/setTime.js');
//获取dom对象
var domMinute_p = document.getElementById('Minute_p');
var domSecond_p = document.getElementById('Second_p');
worker.postMessage(600); //这里可以接受worker线程的返回值
worker.onmessage = function(event) {
var totalSecond = event.data;
console.log(totalSecond)
//计算分钟数
var minute_p = parseInt(totalSecond / 60);
domMinute_p.innerText = minute_p;
//计算秒数
var second_p = parseInt(totalSecond % 60);
domSecond_p.innerText = second_p;
}
}
//这里是模拟的耗时操作
function business() {
var data = [1, 2, 3, 4, 5];
for(var i = 1; i < 1000; i++) {
for(var j = 1; j < 1000; j++) {
for(var k = 1; k < 5000; k++) {
var b = k * 100;
}
}
}
console.log("业务终于走完了!")
}

worker线程js代码:

var totalSecond = 600;
var domMinute_p, domSecond_p, //接受事件参数
onmessage = function(e) {
console.log(e.data)
domMinute_p = e.data;
}
var timeId = setInterval(function() {
totalSecond--; if(totalSecond == 0) {
self.close();
}
console.log(totalSecond)
postMessage(totalSecond) }, 1000)

好了大致示例就是这么多。下面是截图效果:

开始运行后编号1会开始倒计时,但是当你点击了编号2进行了模拟耗时后,编号1还是会卡住,只有完成编号2后才会运行,但是不同与上面说到的单线程是,他再次运行时的时间是正确时间,还是刚才的例子如果是9:57,点击编号2模拟耗时了3秒,耗时完成后编号1会显示9:54而不是单线程的9:57。就说明worker现在在耗时操作的时候是持续运行的,时间卡只不过是主线程的dom操作被卡住了而已(可以把耗时业务也开启worker就不卡住了)。这里只是介绍worker的使用,所有就不纠结这个界面显示的问题。

补充界面显示方法:

后来有些人就问我怎弄界面显示,我还是真的心疼你们啊,不知道举一反三吗,当然是吧业务耗时也放到后台线程啊,哈哈!!!

再特此说明一个问题,仅在安卓测试:就是定时器在息屏模式下仍继续执行

我还是上面的例子做个例子:

把耗时业务放到business.js文件

onmessage = function(e) {
console.log(e.data)
for(var i = ; i < ; i++) {
for(var j = ; j < ; j++) {
for(var k = ; k < ; k++) {
var b = k * ;
}
}
}
console.log("耗时业务走完了");
postMessage()
}

然后主文件js调用就好了啊:

                    //这里是模拟的耗时操作
function business() {
var worker = new Worker('js/business.js');
worker.postMessage("开启任务耗时");
worker.onmessage = function(event) {
if(event == ) {
console.log("点击一次完成")
worker.terminate()
} }
}

截图效果:

【worker】js中的多线程的更多相关文章

  1. three.js 中使用多线程以及性能测试

    今天郭先生说一下WebWorker以及WebWorker在three.js中的应用.我们都知道Javascript是单线程的,比如执行js代码的同时UI渲染就会停止,对于多核CPU的点脑,这一点让人难 ...

  2. Web worker 与JS中异步编程的对比

    0.从一道题说起 var t = true; setTimeout(function(){ t = false; }, 1000); while(t){ } alert('end'); 问,以上代码何 ...

  3. 深入HTML5 Web Worker应用实践:多线程编程

    HTML5 中工作线程(Web Worker)简介 至 2008 年 W3C 制定出第一个 HTML5 草案开始,HTML5 承载了越来越多崭新的特性和功能.它不但强化了 Web 系统或网页的表现性能 ...

  4. JS中的异步以及事件轮询机制

    一.JS为何是单线程的? JavaScript语言的一大特点就是单线程,也就是说,同一个时间只能做一件事.那么,为什么JavaScript不能有多个线程呢?这样能提高效率啊.(在JAVA和c#中的异步 ...

  5. 深入 HTML5 Web Worker 应用实践:多线程编程

    深入 HTML5 Web Worker 应用实践:多线程编程 HTML5 中工作线程(Web Worker)简介 至 2008 年 W3C 制定出第一个 HTML5 草案开始,HTML5 承载了越来越 ...

  6. 【面试篇】寒冬求职季之你必须要懂的原生JS(中)

    互联网寒冬之际,各大公司都缩减了HC,甚至是采取了“裁员”措施,在这样的大环境之下,想要获得一份更好的工作,必然需要付出更多的努力. 一年前,也许你搞清楚闭包,this,原型链,就能获得认可.但是现在 ...

  7. 疯狂Html+CSS+JS 中JS总结

    来自:http://mzkmzk.github.io/blog/2015/10/05/amazeing-js/ 0 总结 本书的JS 第一章有讲语法有挺多常见的坑点和原理解释很不错 第二章DOM编程讲 ...

  8. js中的webworker

    js中的webworker webworker的作用类似于java的多线程 以独立文件的形式运行webworker index.html <!DOCTYPE html> <html ...

  9. JavaScript 中的多线程通信的方法

    在Html 5诞生之后,我们可以使用javascript来实现多线程处理.H5 新增了一个web workers api,使用这个API,用户可以很容易地创建在后台运行的线程,H5 中被称为workd ...

随机推荐

  1. 用js实现贪吃蛇

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  2. Web browse的发展演变

    Web browse 译为中文是网络浏览器或网页浏览器. Web浏览器如今可谓遍地开花,无论你最终选择了什么浏览器,你可能都会举得他们的功能性想当然的,但是你们可能不知道这些Web浏览器是20年发展的 ...

  3. 背水一战 Windows 10 (120) - 后台任务: 后台上传任务

    [源码下载] 背水一战 Windows 10 (120) - 后台任务: 后台上传任务 作者:webabcd 介绍背水一战 Windows 10 之 后台任务 后台上传任务 示例演示 uwp 的后台上 ...

  4. FFmpeg 学习(三):将 FFmpeg 移植到 Android平台

    首先需要去FFmpeg的官网http://www.ffmpeg.org/去下载FFmpeg的源码,目前的版本号为FFmpeg3.3(Hilbert). 下载的文件为压缩包,解压后得到ffmpeg-3. ...

  5. PHP LDAP 目录协议函数库

    在 LDAP 的协议之中,很像硬盘目录结构或倒过来的树状结构.LDAP 的根就是全世界,第一级是属于国别 (countries) 性质的层级,之后可能会有公司 (organization) 的层级,接 ...

  6. Javascript高级编程学习笔记(25)—— 函数表达式(3)模仿块级作用域

    昨天写了闭包 今天就来聊聊块级作用域的事情 在绝大多数编程语言中,都有块级作用域这个概念 什么是块级作用域呢? 前面我们在刚开始讲的时候说过,JS中的大括号(不在赋值运算符的后面)表示代码块 块级作用 ...

  7. 3.CursorAdapter

    会话页面 点击菜单时编辑的按钮显示,其余的时候gone ConversationUI  public class ConversationUI extends Activity implements ...

  8. TextView的跑马灯效果实现

    TextView的跑马灯效果实现 问题描述 当文字内容过长,但是只允许显示一行时,可以将文字显示为跑马灯效果,即文字滚动显示. 代码实现 第一种方法实现 先查询TextView控件的属性,得到以下信息 ...

  9. HBase之HRegionServer启动(含与HMaster交互)

    在我的博文<HBase——HMaster启动之一>.<HBase——HMaster启动之二>中已经详细介绍过HMaster在启动过程中调用的各种方法.下面,单就HRegionS ...

  10. C++版 - 剑指offer 面试题31:连续子数组的最大和 题解

    剑指offer:连续子数组的最大和 提交网址: http://www.nowcoder.com/practice/459bd355da1549fa8a49e350bf3df484?tpId=13&am ...