HTML5新特性之Web Workers
2016-03-08 13:09
806 查看
我们知道浏览器端JavaScript是以单线程的方式执行的,也就是说JavaScript和UI渲染占用同一个主线程,那就意味着,如果JavaScript进行高负载的数据处理,UI渲染就很有可能被阻断,从而造成用户体验的大打折扣。Web Workers作为HTML5新特性之一,为浏览器端JavaScript开创了一种新的运行模式,使之能够在另外的线程中创建新的运行环境,以便使JavaScript能够在后台做一些费时的处理。下面我们就来详细介绍一下Web Workers方面的知识。
Web Workers可以通过加载一个脚本文件,进而创建一个独立的工作线程,在主线程之外运行。工作线程的创建比较简单,代码如下:
在创建完工作线程后,我们就可以在主线程中与工作线程通信了。主线程中通过postMessage方法向工作线程发送消息,也可以通过捕获worker实例的message事件来接收来自工作线程的消息。需要注意的是,在postMessage方法中,我们可以相对自由的传递各种类型的数据,但是像document等BOM对象是无法被传递的。下面就让我们来看看主线程中是如何和工作线程交互的:
在某些情况下,我们不得不中断工作线程的运行,主线程中我们可以调用worker实例的terminate方法,在工作线程中我们也可以调用close方法中断自身,代码如下:
我们经常会加入一些技术群组里探讨技术,广交朋友,如果群组成员太多,查看起来就不太方便,为此我们打算给这个群组加一个搜索的功能,根据关键字搜索与成员信息匹配的数据,就像下面图中所示:
在这个案例中,群组成员信息预先加载到了客户端,搜索功能也是在客户端完成的,假如数据非常多,一个简单的搜索可能就会在用户体验上造成不小的折扣,我们打算用Web Workers来实现这个操作。现在来看一下示例项目的基本目录结构:
我们可以看到,在js目录中有个worker.js文件,用于放置工作线程的逻辑代码,此文件在运行时被主线程加载,我们稍后会详细讲解。现在我们先看一下主页面的基本结构:
最后,我们开看看worker.js是如何运行的:
以上就是Web Workers的介绍,在实际开发中,可能面临很多复杂的操作需要在前端完成,我们都可以考虑用Web Workers实现,将复杂操作交给工作线程,进而减少主线程的阻塞,在用户体验上一定会有显著的提升。
Web Workers可以通过加载一个脚本文件,进而创建一个独立的工作线程,在主线程之外运行。工作线程的创建比较简单,代码如下:
var worker = new Worker('js/worker.js');如代码所示,我们只需将含有工作线程的代码文件路径作为参数传入到Worker构造函数中,即可创建一个工作线程,使其能够在后台执行。需要注意的是,脚本的加载有同源策略的限制,所以必须指定与主线程同源的文件。
在创建完工作线程后,我们就可以在主线程中与工作线程通信了。主线程中通过postMessage方法向工作线程发送消息,也可以通过捕获worker实例的message事件来接收来自工作线程的消息。需要注意的是,在postMessage方法中,我们可以相对自由的传递各种类型的数据,但是像document等BOM对象是无法被传递的。下面就让我们来看看主线程中是如何和工作线程交互的:
//message sending worker.postMessage({name: 'Scott'}); //message receiving worker.onmessage = function(event) { var data = event.data; //to do }同样的,在工作线程中我们也可以通过postMessage和onmessage方法来发送和接收数据,下面是工作线程文件worker.js中的代码:
//message sending self.postMessage({name: 'Worker'}); //message receiving self.onmessage = function(event) { var data = event.data; //to do }
在某些情况下,我们不得不中断工作线程的运行,主线程中我们可以调用worker实例的terminate方法,在工作线程中我们也可以调用close方法中断自身,代码如下:
//interrupt a work thread in main thread worker.terminate(); //interrupt work thread it self self.close();以上介绍了Web Workers的基本用法,接下来我们来以一个实例说明它在实际项目中是如何应用的。
我们经常会加入一些技术群组里探讨技术,广交朋友,如果群组成员太多,查看起来就不太方便,为此我们打算给这个群组加一个搜索的功能,根据关键字搜索与成员信息匹配的数据,就像下面图中所示:
在这个案例中,群组成员信息预先加载到了客户端,搜索功能也是在客户端完成的,假如数据非常多,一个简单的搜索可能就会在用户体验上造成不小的折扣,我们打算用Web Workers来实现这个操作。现在来看一下示例项目的基本目录结构:
我们可以看到,在js目录中有个worker.js文件,用于放置工作线程的逻辑代码,此文件在运行时被主线程加载,我们稍后会详细讲解。现在我们先看一下主页面的基本结构:
<html> <head> <title>Web Worker</title> <link rel="stylesheet" type="text/css" href="css/main.css"> </head> <body> <div id="searching"> <input id="keywords" type="text" placeholder="type in to start searching"> <button id="search-button" onclick="search();">search</button> <div id="members"> <!-- <div class="member"> <img src="img/icon.png"> <div class="info"> <p>John Li</p> <p>Java programming, Python language</p> </div> <a class="add">+Add</a> </div> --> <!-- the search results will be here --> </div> </div> <script type="text/javascript" src="js/jquery.js"></script> <script type="text/javascript" src="js/main.js"></script> </body> </html>看起来很简单,一个搜索框和搜索按钮,下面是搜索结果显示区域。为了使其运行起来,我们还需要main.js的配合,代码如下:
//a simple group member data example var groupMembers = [ { id: 101, name: 'John Li', skills: 'Java programming, Python language, MySQL' }, { id: 102, name: 'Lisa Wang', skills: 'HTML, JavaScript, CSS, Node.js' }, { id: 103, name: 'Tom Wang', skills: 'JavaScript, CSS, HTML5' }, { id: 104, name: 'Andy Zhang', skills: 'PHP language, JavaScript programming, CSS' } /* a large number of data */ ]; //loading the worker.js to instantiate a Worker object var worker = new Worker('js/worker.js'); //receive message from work thread, and then render the result data worker.onmessage = function(e) { renderGroupMembers(e.data.results); }; function search() { var keywords = $('#keywords').val().trim(); //post a message to work thread worker.postMessage({ groupMembers: groupMembers, keywords: keywords }); } function renderGroupMembers(members) { var html = ''; members.forEach(function(member) { var resultHtml = '<div class="member">' + ' <img class="icon" src="img/icon.png">' + ' <div class="info">' + ' <p>' + member.name + '</p>' + ' <p>' + member.skills + '</p>' + ' </div>' + ' <a class="add">+Add</a>' + '</div>'; html += resultHtml; }); $('#members').html(html); } renderGroupMembers(groupMembers);在这段代码中,我们首先会加载worker.js,实例化一个Worker对象,然后捕获message事件,进而将搜索结果显示到相应区域。而search函数负责监听搜索按钮的点击事件,然后向工作线程发送带有群组数据和关键字的消息,将搜索任务交给工作线程。
最后,我们开看看worker.js是如何运行的:
//receive the message from main thread self.onmessage = function(e) { var groupMembers = e.data.groupMembers; var keywords = e.data.keywords; var results = searchByKeywords(groupMembers, keywords); //post the result message to main thread self.postMessage({results: results}); }; //it may be quite complicated in real application function searchByKeywords(groupMembers, keywords) { var results = []; keywords = keywords.toLowerCase(); groupMembers.forEach(function(member) { var nameMatched = member.name.toLowerCase().indexOf(keywords) > -1; var skillsMatched = member.skills.toLowerCase().indexOf(keywords) > -1; if (nameMatched || skillsMatched) { results.push(member); } }); return results; }从上面的代码中可以看到,首先我们会捕获工作线程的message事件,接收群组数据和关键字,然后调用搜索函数,最后将搜索结果发送回主线程,完成这次的搜索任务。
以上就是Web Workers的介绍,在实际开发中,可能面临很多复杂的操作需要在前端完成,我们都可以考虑用Web Workers实现,将复杂操作交给工作线程,进而减少主线程的阻塞,在用户体验上一定会有显著的提升。
相关文章推荐
- html5篇——新增表单元素和表单属性
- HTML5 canvas绘制雪花飘落动画(需求分析、知识点、程序编写分布详解)
- HTML5外包
- 2015 年最棒的 5 个 HTML5 框架
- 2015 年最棒的 5 个 HTML5 框架
- html5的新增的标签和废除的标签
- 【HTML5初涉】新增主体结构元素和非主体结构元素
- 【HTML5初涉】H5与H4的区别
- 多文件上传插件Stream,解决不同浏览器上传文件的插件,是Uploadify的Flash版和Html5版的结合,带进度条,并支持html5断点续传,拖拽等功能
- HTML5 canvas绘制雪花飘落动画(需求分析、知识点、程序编写分布详解)
- 移动前端头部标签(HTML5 head meta)
- HTML5的video标签,视频在网页播放没有画面只有声音,支持的格式,MP4,
- 2015 年最棒的 5 个 HTML5 框架
- HTML5 canvas绘制雪花飘落动画(需求分析、知识点、程序编写分布详解)
- HTML5学习(一)
- HTML5之canvas标签(上)
- html5
- HTML5 构架
- HTML5 网页制作
- HTML5中的标签