Web Workers允许你在后台运行JavaScript代码,而不会阻止web用户界面。Web Workers可以提高网页的整体性能,还可以增强用户体验。Web Workers有两种风格 ——专用Web Workers和共享Web Workers。本文讨论了你所需要知道的Web worker的七个关键方面,帮助你决定在应用程序中使用它们的话。
通常,你在Web页面中编写的JavaScript代码在与用户界面相同的线程中执行。这就是为什么当你点击一个会触发漫长处理过程的按钮,网页的用户界面会冻结。除非处理完成,否则你就无法工作于用户界面。Web worker允许你在后台执行JavaScript,以便用户界面保持响应,即使同时正在执行某些脚本。执行脚本的后台线程通常称为worker thread或worker。你可以生成尽可能多的worker,只要你想。你还可以将数据传递到正在worker thread中执行的脚本,并在完成时将值返回到主线程。然而,Web Workers有一些限制,如下所示:
但是,你可以使用setTimeout(),setInterval()等函数。你也可以使用XMLHttpRequest对象向服务器发出Ajax请求。
Web Workers有两种类型:专用Web Workers和共享Web Workers。专用Web Workers随同创建它们的网页一起存在和死亡。这意味着在网页中创建的专用Web Workers无法通过多个网页访问。另一方面,共享Web Workers在多个网页之间是共享的。Worker类代表专用Web Workers,而SharedWorker类代表共享Web Workers。
在许多情况下,专用Web Workers就可以满足你的需求。这是因为通常你需要在worker thread中执行一个网页的特定脚本。然而,有时,你需要在worker thread中执行一个脚本,并且这个worker thread对多个网页通用。在这种情况下,创建许多专用Web Workers,每个页面一个,还不如使用共享Web Workers。由一个网页创建的共享web worker仍然可用于其他网页。只有当所有到它的连接被关闭,才能毁坏它。共享Web Workers比专用Web Workers更复杂一点。
现在,你了解了Web Workers的基础知识,让我们看看如何使用专用Web Workers。下面讨论的示例假设你已使用喜欢的开发工具创建了一个Web应用程序,并且还在其Script文件夹中添加了jquery和Modernizr库。将html页面添加到web应用程序,然后键入以下代码:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script src="scripts/modernizr.js"></script>
<script src="scripts/jquery-2.0.0.js"></script>
<script type="text/javascript">
$(document).ready(function () {
if (!Modernizr.webworkers)
{
alert("This browser doesn't support Web Workers!");
return;
}
$("#btnStart").click(function () {
var worker = new Worker("scripts/lengthytask.js");
worker.addEventListener("message", function (evt) {
alert(evt.data);
},false);
worker.postMessage(10000);
});
});
</script>
</head>
<body>
<form>
<input type="button" id="btnStart" value="Start Processing" />
</form>
</body>
</html>
上面的HTML页面包含一个触发一些JavaScript处理的按钮(btnStart)。请注意,该网页引用了Modernizr和jQuery库。<script>块包括ready()方法处理程序,并且该处理程序又反过来处理btnStart的单击事件。ready()处理程序首先检查浏览器是否支持web workers。这通过使用Modernizr的webworkers属性完成。如果浏览器不支持Web workers,则会向用户显示一条错误消息。
然后代码连接btnStart的点击事件处理程序。点击事件处理程序的代码很重要,因为它使用Worker对象在后台运行脚本。点击事件处理程序创建一个Worker对象并将其存储在本地变量——worker中。要在后台执行的JavaScript文件的路径在构造函数中传递。你将很快创建LengthyTask.js。然后,代码为Worker对象的消息事件添加一个事件处理程序。当目标脚本(在此情况下为LengthyTask.js)将一些值发送回网页时,会引发消息事件。消息事件处理函数可以使用evt.data属性来访问返回的值。最后,在Worker对象上调用postMessage()方法来触发LengthyTask.js的执行。 postMessage()方法还允许你将数据传递到目标脚本。在此示例中,将一个数字(10000)传递给postMessage(),postMessage()指示处理应持续的毫秒数量。你可以传递postMessage()调用中的任何其他数据,如JavaScript对象或字符串。
LengthyTask.js文件包含要在后台执行的代码,如下所示:
addEventListener("message", function (evt) {
var date = new Date();
var currentDate = null;
do {
currentDate = new Date();
} while (currentDate - date < evt.data);
postMessage(currentDate);
}, false);
上面的代码处理worker thread的消息事件。当主页面调用Worker对象上的postMessage()方法时,会引发消息事件。消息事件处理程序通过运行某些毫秒的do-while循环来模拟冗长的处理。此循环运行的毫秒数从主页传递(回忆前面讨论的postMessage())。因此,evt.data在此示例中返回10000。一旦长时间操作完成,代码调用postMessage()会把处理结果发送回主页面。在本例中,传递currentDate的值(currentDate是一个Date对象)。
如果你运行主网页并单击Start Processing按钮,那么你将在10秒后收到alert()。同时,页面的用户界面不会被阻止,你可以执行诸如滚动,点击等操作,表明来自LengthyTask.js的代码正在后台运行。
前面的示例使用了专用Web worker。让我们将同样的示例转换为使用共享Web worker。共享Web worker由SharedWorker对象表示。下面的代码显示了来自主页的代码的修改版本:
$(document).ready(function () {
if (!Modernizr.webworkers)
{
alert("This browser doesn't support Web Workers!");
return;
}
$("#btnStart").click(function () {
var worker = new SharedWorker("scripts/sharedlengthytask.js"); worker.port.addEventListener("message", function (evt) { alert(evt.data); }, false); worker.port.start(); worker.port.postMessage(10000); });
});
注意用粗体字标记的代码。它创建了一个SharedWorker实例,并在构造函数中传递SharedLengthyTask.js。你将很快创建此文件。然后,代码将消息事件处理程序连接到SharedWorker对象的端口对象。消息处理程序函数执行与前面示例中相同的工作。然后代码在端口对象上调用start()方法。最后,在端口对象上调用postMessage()方法将数据(10000)发送到共享worker thread。
SharedLengthyTask.js文件包含以下代码:
var port;
addEventListener("connect", function (evt) {
port = evt.ports[0];
port.addEventListener("message", function (evt) {
var date = new Date();
var currentDate = null;
do {
currentDate = new Date();
} while (currentDate - date < evt.data);
port.postMessage(currentDate);
}, false);
port.start();
}, false);
代码首先声明一个名为port的变量,用于存储端口对象的引用。这次处理了两个事件——connect和message。当与共享Web worker建立连接时,会触发connect事件。 connect事件处理程序捕获evt.port [0]对象并将其存储在之前声明的端口变量中。然后在端口对象上连接消息事件处理程序。调用端口对象的start()方法来开始侦听该端口上的消息。消息事件处理程序几乎与你在前面的示例中编写的消息事件处理程序相同,除了它附加到端口对象这一点。此外,在端口对象上调用postMessage(),以将处理结果发送到主页面。
有时Web Worker可能需要与Web服务器通信。例如,你可能需要驻留在某些RDBMS中的数据以便于客户端处理。要完成此类任务,你可以使用XMLHttpRequest对象向服务器端资源发出请求。实例化Worker对象和处理消息事件的整个过程保持不变。但是,你需要向服务器端资源发出GET或POST请求。考虑下面的代码:
addEventListener("message", function (evt) {
var xhr = new XMLHttpRequest(); xhr.open("GET", "lengthytaskhandler.ashx"); xhr.onload = function () { postMessage(xhr.responseText); }; xhr.send(); }, false);
上面显示的代码创建了XMLHttpRequest对象的实例。然后调用open()方法,并指定向服务器端资源LengthyTaskHandler.ashx(一个ASP.NET通用处理程序)发出GET请求。(虽然此示例使用ASP.NET通用处理程序,但你可以使用任何其他服务器端资源。)然后它处理XMLHttpRequest对象的load事件并调用postMessage()。 xhr.responseText作为postMessage()的参数。xhr.responseText将是ASP.NET通用处理程序作为响应返回的值。请求完成时引发load事件。
LengthyTaskHandler.ashx包含以下代码:
namespace WebWorkersDemo
{
public class LengthyTaskHandler : IHttpHandler
{
public void ProcessRequest(HttpContext context) { System.Threading.Thread.Sleep(10000); context.Response.ContentType = "text/plain"; context.Response.Write("Processing successful!"); }
public bool IsReusable
{
get
{
return false;
}
}
}
}
正如你可以看到,ProcessRequest()通过在Thread类上调用Sleep()方法来模拟一些冗长的处理,并阻止执行10秒。然后它返回一个成功消息“Processing successful!”给调用者。如果你在进行这些更改后运行主网页,你会发现在10秒后,将显示一个包含此成功消息的警报对话框。
如果你的Web worker正在进行一些复杂的操作,那么你可能需要添加错误处理到主网页代码,以便在worker中出现任何未处理错误时,可以采取适当的操作。这可以通过处理Worker对象的错误事件来完成。每当work thread中存在任何未处理的错误时,就会抛出错误事件。以下代码显示了如何完成此操作:
$("#btnStart").click(function () {
var worker = new Worker("scripts/lengthytask.js");
worker.addEventListener("message", function (evt) {
alert(evt.data);
}, false);
worker.addEventListener("error", function (evt) { alert("Line #" + evt.lineno + " - " + evt.message + " in " + evt.filename); }, false); worker.postMessage(10000);
});
从上面的代码可以看出,错误处理程序已经连接到worker对象的错误事件。错误处理函数接收一个事件对象,而该对象提供错误信息,例如发生错误的行号(evt.lineno),错误消息(evt.message)和发生错误的文件(evt.filename)。
有时你可能会想要取消worker中正在执行的任务。对此,你可以通过调用其terminate()方法来摧毁Worker。一旦Worker终止,你就不能重新使用或重新启动它。当然,你总是可以创建另一个Worker实例并使用它。但请记住,terminate()会立即杀死了worker,并且不会给你任何机执行清理操作。
Web workers允许你在后台执行脚本而不冻结网页用户界面。有两种类型——专用web worker和共享web worker。每个网页创建专用web worker,而跨多个网页使用共享web worker共享。Worker类代表专用web worker,SharedWorker类代表共享web worker。本文介绍了如何使用这两种类型,文中还讨论了如何处理错误以及webworker如何使用XMLHttpRequest与web服务器通信。
service worker的生命周期是它最复杂的部分。如果你不知道它在努力做什么和这么做的优势,你会感到它在跟你对着干。但一旦你知道了它的原理,你就可以给用户提供无缝的,优雅而不突兀的更新。一种同时具备网站应用和原生应用优势的体验。
web worker 是运行在后台的 JavaScript,独立于其他脚本,也就是说在Javascript单线程执行的基础上,开启一个子线程,进行程序处理,而不影响主线程的执行。Service Worker 是一个由事件驱动的 worker,它由源和路径组成,以加载 .js 文件的方式实现的。
Web Worker 是为了解决 JavaScript 在浏览器环境中没有多线程的问题。正常形况下,浏览器执行某段程序的时候会阻塞直到运行结束后在恢复到正常状态,而HTML5的Web Worker就是为了解决这个问题,提升程序的执行效率。
思路:五个人(5个div窗口模拟)同时进行抢票,有百分之十的几率可以抢到票,抢到票后对应的窗口(即随机生成的数大于等于0小于9的情况)会编程天蓝色,没抢到票的窗口(即随机生成的数大于9小于100的情况)会变成红色
想要明白workers,首先需要明白node是怎样构成的。当一个node进程开始,它其实是:一个进程:是指一个全局对象,这个对象能够访问任何地方,并且包含当前处理时的此时信息。
作为前端,在消费接口提供的数据时,往往由于数据实际分布在不同地方(如一部分存储在 ODPS ,而另一部分可能更适合在应用初始化时从本地载入内存)而需要对数据进行区分处理。当然,交互的实现可能也会需要很重的计算逻辑
作为浏览器脚本语言,如果JavaScript不是单线程,那么就有点棘手了。比如,与用户交互或者对DOM进行操作时,在一个线程上修改某个DOM,另外的线程删除DOM,这时浏览器该如何抉择呢?
Web 是单线程的。这让编写流畅又灵敏的应用程序变得越来越困难。Web Worker 的名声很臭,但对 Web 开发者来说,它是解决流畅度问题的 一个非常重要的工具。让我们来了解一下 Web Worker 吧
多线程是现代软件开发中用于增强应用的性能和响应能力的重要技术。然而,JavaScript 是一门单线程语言,它天生是不支持多线程的。为了克服这一限制,引入了 Web Workers。本文就来探讨 Web Workers 对 Web 多线程的重要性,以及使用它们的限制和注意事项。
内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!