HTML5 – Web Workers
JavaScript被设计成在单线程环境中运行,意味着多个脚本无法同时运行。考虑一种情况,您需要处理UI事件、查询和处理大量API数据以及操作DOM。
当CPU利用率高的情况下,JavaScript会使您的浏览器挂起。让我们以一个简单的例子来说明JavaScript的问题,JavaScript通过一个大循环的情况:
<!DOCTYPE HTML>
<html>
<head>
<title>大循环</title>
<script>
function bigLoop() {
for (var i = 0; i <= 10000; i += 1) {
var j = i;
}
alert("已完成 " + j + " 次迭代");
}
function sayHello(){
alert("您好先生....");
}
</script>
</head>
<body>
<input type = "button" onclick = "bigLoop();" value = "Big Loop" />
<input type = "button" onclick = "sayHello();" value = "Say Hello" />
</body>
</html>
它将产生以下结果 –
当您点击“Big Loop”按钮时,在Firefox中显示以下结果 –
什么是Web Workers?
上述情况可以使用 Web Workers 进行处理,Web Workers将执行所有计算密集型任务,而不会中断用户界面并通常在单独的线程上运行。
Web Workers允许长时间运行的脚本,这些脚本不会被响应点击或其他用户交互的脚本中断,并允许执行长时间任务而无需放弃以保持页面响应。
Web Workers是后台脚本,它们相对较重,不适合大量使用。例如,在每个四兆像素图像的每个像素中启动一个工作线程是不合适的。
当脚本在Web Worker中执行时,它不能访问Web页面的window对象(window.document),这意味着Web Workers没有直接访问Web页面和DOM API的权限。虽然Web Workers无法阻止浏览器UI,但它们仍然可以消耗CPU周期并使系统反应不够灵敏。
Web Workers如何工作?
Web Workers使用JavaScript文件的URL初始化,该文件包含工作线程将执行的代码。这段代码设置事件侦听器并与从主页面生成的脚本通信。下面是简单的语法:
var worker = new Worker('bigLoop.js');
如果指定的JavaScript文件存在,则浏览器将生成一个新的工作线程,该线程将异步下载。如果您的路径返回404错误,则工作线程将默默地失败。
如果您的应用程序具有多个支持JavaScript文件,则可以使用 importScripts() 方法将它们导入,该方法以文件名(由逗号分隔的参数)作为参数,如下所示:
importScripts("helper.js", "anotherHelper.js");
一旦Web Worker被启动,Web Worker与其父页面之间的通信使用 postMessage() 方法进行。根据您的浏览器/版本,postMessage()可以将字符串或JSON对象作为其单个参数接受。
Web Worker传递的消息使用主页面中的 onmessage 事件来访问。现在让我们使用Web Worker编写我们的bigLoop示例。以下是主页面(hello.htm),它将生成一个Web Worker来执行循环并返回变量 j 的最终值:
<!DOCTYPE HTML>
<html>
<head>
<title>大循环</title>
<script>
var worker = new Worker('bigLoop.js');
worker.onmessage = function (event) {
alert("已完成" + event.data + "次迭代");
};
function sayHello() {
alert("您好....");
}
</script>
</head>
<body>
<input type = "button" onclick = "sayHello();" value = "打招呼"/>
</body>
</html>
下面是bigLoop.js文件的内容。此文件使用 postMessage() API将通信传回主页−
for (var i = 0; i <= 1000000000; i += 1) {
var j = i;
}
postMessage(j);
这将产生以下结果 −
停止 Web Workers
Web Workers自己无法停止,但启动它们的页面可以通过调用 terminate() 方法来停止它们。
worker.terminate();
终止的Web Worker将不再响应消息或执行任何其他计算。您无法重新启动工作者;相反,您可以使用相同的URL创建新的工作者。
错误处理
以下显示了在Web Worker JavaScript文件中记录错误到控制台的错误处理函数示例。通过错误处理代码,上面的示例将变为以下样式−
<!DOCTYPE HTML>
<html>
<head>
<title>大循环</title>
<script>
var worker = new Worker('bigLoop.js');
worker.onmessage = function (event) {
alert("已完成" + event.data + "次迭代");
};
worker.onerror = function (event) {
console.log(event.message, event);
};
function sayHello() {
alert("您好....");
}
</script>
</head>
<body>
<input type = "button" onclick = "sayHello();" value = "打招呼"/>
</body>
</html>
检查浏览器支持
以下是检测浏览器中Web Worker功能是否受支持的语法−
<!DOCTYPE HTML>
<html>
<head>
<title>大循环</title>
<script src = "/js/modernizr-1.5.min.js"></script>
<script>
function myFunction() {
if (Modernizr.webworkers) {
alert("恭喜您!!您有Web Workers支持。");
} else {
alert("对不起!!您没有Web Workers支持。");
}
}
</script>
</head>
<body>
<button onclick = "myFunction()">点我</button>
</body>
</html>
这将产生以下结果 −