因为下个项目中要用到一些倒计时的功能,所以就提前准备了一下,省的到时候出现一下界面不友好和一些其他的事情。正好趁着这个机会也加深一下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. Python基础知识当中容易混淆的几个知识点

    在Python的基础知识当中,对于类实现可迭代功能有了一种新的方式,而这种方式则有别于我们学.NET等其他高级语言. 在Python当中,目前常用的有两种方式来实现这种迭代器的返回:__iter__ ...

  2. junit 方法:assertEquals 和 assertTrue

    assertEquals 和 assertTrue 区别相同之处:都能判断两个值是否相等 assertTrue 如果为true,则运行success,反之Failure assertEquals 如果 ...

  3. centos7的Kubernetes部署记录

    一.使用vm创建了三个centos系统,基本细节如下: 1.1 修改三台机器对应的主机名: [root@localhost ~] hostnamectl --static set-hostname k ...

  4. 《JavaScript 高级程序设计》读书笔记五 引用类型

    一   Object类型 a.两种创建方式: 1.new+构造函数Object; 2.对象字面量表示法: b.两种访问属性方式: 1.点表示法(.属性): 2.方括号([“属性”]): 二   Arr ...

  5. 网络编程懒人入门(九):通俗讲解,有了IP地址,为何还要用MAC地址?

    1.前言 标题虽然是为了解释有了 IP 地址,为什么还要用 MAC 地址,但是本文的重点在于理解为什么要有 IP 这样的东西.本文对读者的定位是知道 MAC 地址是什么,IP 地址是什么. (本文同步 ...

  6. js高级笔记

    定时器this指向window javascript 的执行过程 预解析(变量) 数据集和功能集---- 对象 对象----属性和方法 -------------------面向对象--------- ...

  7. Python学习笔记【第九篇】:Python面向对象基础

    Python语言中一切皆对象(类.属性.方法.........) 概念 面向对象编程:Object Oriented Programming 简称OOP 面向对象程序设计 面向对象和面向过程都是解决问 ...

  8. 在Ubuntu 18.04中安装pyenv(Python多版本管理工具)

    最近正在重头梳理Python的基础知识,为了更好地使用Python进行开发,防止发生版本混乱(不同的第三方库有可能因为Python版本不兼容而报错),所以需要使用pyenv进行版本管理. *** 通常 ...

  9. lazy_import源码解析(原创)

    参考链接: An approach to lazy importing in Python 3.7(这个是参考源) Python3.7中一种懒加载的方式(中文翻译) 原博客核心: 以前的两种惰性/延迟 ...

  10. Java核心技术及面试指南 数据库方面的面试题归纳以及总结

    5.1.7.1 事务的四大特性是什么? ⑴ 原子性(Atomicity) 原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚. ⑵ 一致性(Consistency) 一致性是指事务必须使数据库 ...