HTML5 API:

1、文件 API (规范与本地文件进行交互的标准方法)2、拖放 API (提供了直接支持拖放操作的API)3、地理定位 (获取地理位置信息)4、web 存储 (在本地存储用户的浏览数据)    5、Web SQL   (在浏览器上模拟数据库,可以使用JS来操作SQL完成对数据的读写)6、应用程序缓存 (创建 web 应用的离线版本。可以在没有网络连接的情况下进行访问。)7、Web Sockets (在WebSocket API中,浏览器和服务器只需要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送。)8、SSE  (网页自动获取来自服务器的更新)9、Web Workers (web worker 是运行在后台的 JavaScript,不会影响页面的性能)......

9、Web Workers (使用Web Workers处理线程)

  • 基础知识
  • 与线程进行数据的交互
  • 线程嵌套
  • 线程中可用的变量、函数与类

本章介绍HTML5新增的与线程有关的一个功能—使用Web Workers来实现Web平台上的多线程处理功能。通过Web Workers,你可以创建一个不会影响前台处理的后台线程,并且在这个后台线程中创建多个子线程。通过Web Workers,你可以将耗时较长的处理交给后台线程去运行,从而解决了HTML5之前因为某个处理耗时过长而跳出一个提示用户脚本运行时间过长,导致用户不得不结束这个处理的尴尬状况。
学习内容:

  • 掌握Web Workers的基本知识,能够使用Web Workers在Web网站或应用程序中创建一个后台线程。
  • 掌握在前台页面与后台线程进行数据交互时所使用到的方法与事件,能够在JavaScript脚本中实现前台页面与后台线程之间的数据交互。
  • 掌握在主线程之间嵌套子线程的方法,能够利用JavaScript脚本在主线程之中创建一个或多个子线程,能够实现主线程与子线程,子线程与子线程之间的数据传递。
  • 了解在后台线程中可以使用的JavaScript 脚本中的对象、方法与事件。

基础知识

Web Workers是在HTML5中新增的,用来在Web应用程序中实现后台处理的一项技术。
在使用HTML4与JavaScript创建出来的web应用程序中,因为所有的处理都是在单线程内执行的所以如果花费的时间比较长的话,程序界面会处于长时间没有响应的状态。最恶劣的是,当时间长到一定程度的话,浏览器还会跳出一个提示脚本运行时间过长的提示框,使用户不得不中断正在执行的处理。
为了解决这个问题,HTML5新增了一个Web Workers API。使用这个API,用户可以很容易地创建在后台运行的线程(在HTML5中被称为worker),如果将可能耗费较长时间的处理交给后台去做的话,对用户在前台页面中执行的操作就完全没有影响了。
创建后台线程的步骤十分简单。只要在Worker类的构造器中,将需要在后台线程中执行的脚本文件的URL地址作为参数,饭后创建Workers对象就可以了,如下所示:
var worker = new Worker(“worker.js”);
但是,要注意在后台线程中是不能访问页面面或窗口对象的。如果在后台线程的脚本文件使用到window对象或document对象,则会引起错误的发生。
另外,可以通过发送和接收消息来与后台线程互相传递数据。通过对Worker对象的onmessage事件句柄的获取可以在后台线程之中接收消息,如下所示:
worker.onmessage = function(event){
//处理收到的消息
}

使用worker对象的postMessage方法来对后台线程发送消息,如下例所示。发送的消息是文本数据,但也可以是任何JavaScript对象(需要通过JSON对象的stringify方法将其转换成文本数据

)。
worker.postMessage(message);
另外,同样可以通过Worker对象的onmessage事件句柄及Worker对像的postMessage方法在后台线程内部进行消息的接收和发送。
接下来,让我们看一个使用后台线程的示例。在该示例中放置了一个文本框,用户在该文本框输入数字,然后点击旁边的计算按钮,在后台计算从1到给定的合计值,虽然对于从1到给定值得求和计算只需要一个求和公式就可以了,但是本示例中为了展示后台线程的使用方法,采用循环计算的方法。
首先给出HTML4中的关于这个求和运算的示例代码。

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>workers</title>
</head>
<body><h1>从1到给定数值的求和:</h1>输入数值:<input type="text" id="num"><button onclick="calculate()">计算</button></body>
<script>function calculate(){var num = parseInt(document.getElementById("num").value, 10);var result = 0;//循环计算求和for(var i = 0; i <= num ; i++){result += i}alert("合计值为:" + result)}
</script>
</html>

执行这段代码的时候,在数值文本框中输入数值,在点击计算按钮之后,并在弹出合计值消息框之前,用户是不能再该页面上进行操作的。另外虽然用户在文本框柱输入比较小的值时,不会有什么问题,但是当用户输入100亿以上的值时,浏览器会弹出一个框,提示脚本执行运行时间过长的对话框,导致用户不得不停止当前计算。

在HTML5 中,可以对上例子重写,使用WebWorkers API让耗时较长的运算在后台运行,这样在上例的文本框无论输入多大的数值都可以正常运算了。代码如下:

HTML
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>workers</title>
</head>
<body><h1>从1到给定数值的求和:</h1>输入数值:<input type="text" id="num"><button onclick="calculate()">计算</button>
</body>
<script>//创建执行运算的线程var worker = new Worker("SumCalculate.js");//接收从线程中传出的计算结果worker.onmessage = function(event){//消息文本放置在data属性中,可以使任何JavaScript对象alert("h合计值为:" + event.data)};function calculate(){var num = parseInt(document.getElementById("num").value, 10);//将值传给线程worker.postMessage(num)}
</script>
</html>SumCalculate.js:
onmessage = function(event){var num = event.data;var result = 0;for(var i = 0; i <= num; i++){result += i;}//向线程创建源送回消息postMessage(result);
}

与线程进行数据的交互
上一节中我们介绍过,使用后台线程时不能访问页面或窗口对象,但是并不代表后台线程不能与页面之间进行数据交互。
与线程进行数据交互示例(与上一个示例道理一样):

html:
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>与线程进行数据交互</title>
</head>
<body><h1>从随机生成的数字中抽取3的倍数并显示示例</h1><table id="table"></table>
</body>
<script>var intArray = new Array(100);var intStr = "";for (let i = 0; i < 100; i++) {intArray[i] = parseInt(Math.random()*100);if(i != 0)intStr += ';';intStr += intArray[i];}//向后台进程提交随机数组var worker = new Worker("script.js");worker.postMessage(intStr);//从线程中取得计算结果worker.onmessage = function(event){if(event.data != ""){var j,k,tr,td;var intArray = event.data.split(';');var table = document.getElementById('table');for (var  i = 0; i < intArray.length; i++) {j = parseInt(i/10,0);k = i%10;//改行不存在if(k==0){//添加行tr = document.createElement('tr');tr.id = "tr" + j;table.appendChild(tr);}//该行已存在else{//huo获取该行tr = document.getElementById("tr" + j);}//添加列td = document.createElement("td");tr.appendChild(td);//设置该列内容td.innerHTML = intArray[j*10 + k];//设置该列背景色td.style.backgroundColor = "blue";//设置该列字体颜色td.style.color = "white";//设置列宽td.width = "30px";}}};
</script>
</html>
script.js
onmessage = function(e){var data = e.data;var returnStr;var intArray = data.split(';');returnStr = "";for (var i = 0; i < intArray.length; i++) {if(parseInt(intArray[i])%3 == 0){if(returnStr != "")returnStr += ";";returnStr += intArray[i]}}postMessage(returnStr);
}

线程嵌套
线程中可以嵌套子线程,这样的话,我们可以把一个较大的后台线程切分成几个子线程,在每个子线程中各自完成相对独立的一部分工作

  • 单层嵌套
    单层嵌套示例的HTML5页面代码:
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>单层嵌套</title>
</head>
<body><h1>从随机生成的数字中抽取3的倍数并显示示例</h1><table id="table"></table></body><script>var worker = new Worker("worker1.js");worker.postMessage("");//从线程中取得计算结果worker.onmessage = function(event){if(event.data != ""){var j,k,tr,td;var intArray = event.data.split(';');var table = document.getElementById('table');for (var  i = 0; i < intArray.length; i++) {j = parseInt(i/10,0);k = i%10;//改行不存在if(k==0){//添加行tr = document.createElement('tr');tr.id = "tr" + j;table.appendChild(tr);}//该行已存在else{//huo获取该行tr = document.getElementById("tr" + j);}//添加列td = document.createElement("td");tr.appendChild(td);//设置该列内容td.innerHTML = intArray[j*10 + k];//设置该列背景色td.style.backgroundColor = "blue";//设置该列字体颜色td.style.color = "white";//设置列宽td.width = "30px";}}};</script>
</html>

后台线程的主线程代码部分即worker1.js:

onmessage = function(){var intArray = new Array(100);for (var i = 0; i < 100; i++) {intArray[i] = parseInt(Math.random()*100);}//创建子线程var worker;worker = new Worker("worker2.js");  //运行后报错:Uncaught ReferenceError: Worker is not defined。这里好像在后台不能得到Worker这个函数吧,书本上的例子,不知道书本上是怎么运行的,找了好多也没找到如如何解决,后面的多个子进程也是一样。如果你知道请告诉我一下哈,这个问题纠结了好久,在这先谢谢了。worker.postMessage(JSON.stringify(intArray));worker.onmessage = function(event){postMessage(event.data);}
}

注意:本例中向子线程中提交消息时使用的是worker.postMessage方法,而向主页面提交消息时使用postMessage方法。在线程中,向子线程提交消息时使用子线程对象的postMessage方法,而向本线程的创建源发送消息时直接使用postMessage方法。

子线程代码:

onmessage = function(event){var intArray = JSON.parse(event.data);var returnStr;var intArray = data.split(';');returnStr = "";for (var i = 0; i < intArray.length; i++) {if(parseInt(intArray[i]) %3 == 0){if(returnStr != "")returnStr += ";";returnStr += intArray[i]}}postMessage(returnStr);close();
}

注意在子线程向发送源发送回消息后,最好使用close语句关闭子线程,如果该子线程不再使用的话。

在多个子线程中进行数据的交互

当主线程使用多个子线程时,多个子线程之间如何实现数据的交互。
要实现子线程与子线程之间的数据交互,大致需要如下几个步骤:

  1. 先创建发送数据的子线程
  2. 执行子线程中的任务,然后把要传递的数据发送给主线程
  3. 在主线程接收到了子线程传回来的消息时,创建接收数据的子线程,然后把发发送数据的子线程中返回的消息传递给接收数据的子线程。
  4. 执行接收数据子线程中的代码。
    代码如下:
HTML代码:
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title></title>
</head>
<body><h1>从随机生成的数字中抽取3的倍数并显示示例</h1><table id="table"></table></body><script>var worker = new Worker("worker1.js");worker.postMessage("");//从线程中取得计算结果worker.onmessage = function(event){if(event.data != ""){var j,k,tr,td;var intArray = event.data.split(';');var table = document.getElementById('table');for (var  i = 0; i < intArray.length; i++) {j = parseInt(i/10,0);k = i%10;//改行不存在if(k==0){//添加行tr = document.createElement('tr');tr.id = "tr" + j;table.appendChild(tr);}//该行已存在else{//huo获取该行tr = document.getElementById("tr" + j);}//添加列td = document.createElement("td");tr.appendChild(td);//设置该列内容td.innerHTML = intArray[j*10 + k];//设置该列背景色td.style.backgroundColor = "blue";//设置该列字体颜色td.style.color = "white";//设置列宽td.width = "30px";}}};</script>
</html>主线程 worker1.js中的代码
onmessage = function(e){var worker;//创建发送数据的子线程worker = new Worker("worker2.js");worker.postMessage("");worker.onmessage = function(e){//接收子线程中的数据,本示例为创建好的随机数组var data = e.data;//创建接收数据子线程;worker = new Worker("worker3.js");//把从发送数据的子线程中发回的消息传递给接收数据的子线程worker.postMessage(data);worker.onmessage = function(e){//获取接收数据的子线程中传回的数据,本例中为挑选结果var data = e.data;//把挑选结果发送回主页面postMessage(data);}}
}发送数据(本例中为创建好的随机数组)的子线程1 worker2.js:
onmessage = function(){var intArray = new Array(100);for (var i = 0; i < 100; i++) {intArray[i] = parseInt(Math.random()*100);}//发回随机数组postMessage(JSON.stringify(intArray));//关闭子进程close();
}接收数据并发回挑选结果的子进程2 worker3.js:
onmessage = function(event){var intArray = JSON.parse(event.data);var returnStr;var intArray = data.split(';');returnStr = "";for (var i = 0; i < intArray.length; i++) {if(parseInt(intArray[i]) %3 == 0){if(returnStr != "")returnStr += ";";returnStr += intArray[i]}}postMessage(returnStr);close();
}

线程中可用的变量、函数与类
最后,我们再来总体看一下在线程用的JavaScript脚本文件中所有可用的变量、函数与类,如下所示:
self self关键词用来表示本线程范围内的作用域。
postMessage(message) 向创建线程的源窗口发送消息
onmessage 获取接收消息的事件句柄
importScripts(url)导入其他JavaScript脚本文件。参数为该脚本文件的URL地址,可以导入多个脚本文件如下所示:importScript(‘script1.js’, ‘scripts/script2.js’, ‘script/script3.js’);导入的脚本文件必须与使用该线程文件的页面在同一域中,并在同一个端口中。
navigator对象 与window.navigator对象类似,具有appName、platform、userAgent、appVersion这些属性。
sessionStorage/localStorage 可以在线程中使用Web Storage
XMLHttpRequest 可以在线程中处理Ajax请求。
Web Workers 可以在线程中嵌套线程。
setTimeout/setInterval() 可以在线程中实现定时处理。
close 可以结束本线程
eval()、isNaN()、escape()等 可以使用所有JavaScript核心函数。
object 可以创建和使用本地对象
WebSockets 可以使用WebSockets API来向服务器发送和接收信息。

参考阅读:

  • 《HTML5与CSS3权威指南》
  • w3school 在线教程
  • w3cschool - 编程狮,随时随地学编程

05-HTML5强大的新 API,09-Web Workers相关推荐

  1. HTML5 postMessage 和 onmessage API 详细应用

    HTML5 postMessage 和 onmessage API 详细应用 在学习HTML5的时候发现一位大神的博文,解决了个人的很多疑惑,转载分享给大家 原文地址:https://www.cnbl ...

  2. [HTML5]移动Web应用程序开发 HTML5篇 (四) 多媒体API

    介绍 本系列博客将主要介绍如今大红大紫的移动Web应用程序开发最重要的三个工具:HTML5,JavaScript, CSS3. 本篇是HTML5介绍的第三篇,主要介绍HTML5的Canvas API. ...

  3. 返璞归真 asp.net mvc (10) - asp.net mvc 4.0 新特性之 Web API

    返璞归真 asp.net mvc (10) - asp.net mvc 4.0 新特性之 Web API 原文:返璞归真 asp.net mvc (10) - asp.net mvc 4.0 新特性之 ...

  4. html5直播api,HTML5 VideoAPI,打造自己的Web视频播放器

    本文将使用HTML5提供的VideoAPI做一个自定义的视频播放器,需要用到HTML5提供的video标签.以及HTML5提供的对JavascriptAPI的扩展. 一.基础知识 1.用法 注意:au ...

  5. Java8新特性(二)——强大的Stream API

    一.强大的Stream API 除了Lambda表达式外,Java8另外一项重大更新便是位于java.util.stream.*下的Stream API Stream 是 Java8 中处理集合的关键 ...

  6. html5交互效果,浅谈HTML5 CSS3的新交互特性

    本文标题的这副图片,是用Phosotshop制作的.但是,在搜索引擎中你却无法搜索到它,搜索引擎还没有强大到能够识别图片里面的文字.并且由于图片的体积不算太小,可能网速慢的网友在浏览的时候不得不耐心的 ...

  7. html5中的css特性,浅谈HTML5 CSS3的新交互特性

    本文标题的这副图片,是用phosotshop制作的.但是,在搜索引擎中你却无法搜索到它,搜索引擎还没有强大到能够识别图片里面的文字.并且由于图片的体积不算太小,可能网速慢的网友在浏览的时候不得不耐心的 ...

  8. html5 workers,HTML5 Web Workers

    HTML5 Web Workers 在html5规范中引入了web workers概念,解决客户端JavaScript无法多线程的问题,其定义的worker是指代码的并行线程,不过web worker ...

  9. 【面试】HTML5 有哪些新特性?_声明方式

    最近看了一些与html基础相关的入门教学视频,心得感悟只有:不同特性的标签记住就好了!但理智告诉我,一切还未正式开始.肿么办?-_-# 是不是可以根据具体html的面试问题对理论知识进行认知拓展与实践 ...

最新文章

  1. SQL Server基础操作(此随笔仅作为本人学习进度记录七 !--存储过程)
  2. 15.3 Task Task.Yield和Task.Delay说明
  3. 拿不到offer全额退款 | 第四期人工智能 NLP / CV 课 培训招生
  4. python3 UnicodeEncodeError: 'ascii' 错误
  5. python函数的作用域是什么_python函数的作用域
  6. 推荐一个简洁免费轻量级的思维导向图软件Blumind
  7. 罗克露计算机组成原理书籍,计算机组成原理完整版罗克露全原版.ppt
  8. WPF MVVM 框架
  9. anaconda r 语言_anaconda 配置R语言
  10. 网络流行简笔画图片大全,网络的简笔画图片
  11. 安装webpack powershell出现 Set-ExecutionPolicy : 对注册表项“HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell
  12. [面试] 各大IT公司校园招聘程序猿笔试、面试题集锦
  13. cardboard 效果_如何在iPhone上设置Google Cardboard
  14. Microsoft AjaxToolkits 17. UpdatePanelAnimation控件
  15. CCPC-Wannafly Winter Camp Day8 (Div2, onsite)
  16. acm比赛经验(转)
  17. 航城街道工商联(商会)领导一行莅临联诚发参观考察
  18. 智解京东618——购物狂欢背后的安全暗战
  19. 线控转向系统的carsim与simulink联合仿真
  20. SpringBoot 场景开发多面手成长手册

热门文章

  1. layui点击某列打开并跳转指定tab
  2. yate学习--yatesip.h--class YSIP_API SIPMessage : public RefObject
  3. 知识点滴 - 为什么一般不用铜锅做菜
  4. 黎明觉醒服务器维护什么时候恢复,黎明觉醒健康值怎么恢复 健康值恢复方法详解...
  5. 【研究生本科】怎样轻松搞定开题报告?
  6. jq获取file表单选择文件的路径、名字、大小、类型
  7. 阿里云推荐有礼活动--针对新用户
  8. archlinux/manjaro常用软件推荐
  9. padding外边距
  10. NOI2018/LuoGu P4774屠龙勇士