JavaScript被设计为在单线程环境中运行,这意味着多个脚本不能同时运行。考虑一种情况,您需要处理UI事件,查询和处理大量API数据以及操纵DOM。
当CPU使用率很高时,JavaScript会挂起您的浏览器。让无涯教程举一个简单的示例,其中JavaScript经历一个大循环-
<!DOCTYPE HTML>
<html>
<head>
<title>Big for loop</title>
</span><span class="tag"><script></span><span class="pln">
</span><span class="kwd">function</span><span class="pln"> bigLoop</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">var</span><span class="pln"> i</span><span class="pun">=</span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun"><=</span><span class="pln"> </span><span class="lit">10000</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><span class="kwd">var</span><span class="pln"> j</span><span class="pun">=</span><span class="pln">i</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
alert</span><span class="pun">(</span><span class="str">"Completed "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> j </span><span class="pun">+</span><span class="pln"> </span><span class="str">"iterations"</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">function</span><span class="pln"> sayHello</span><span class="pun">(){</span><span class="pln">
alert</span><span class="pun">(</span><span class="str">"Hello sir...."</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="tag"></script></span><span class="pln">
</head>
<body>
<input type="button" onclick="bigLoop();" value="Big Loop" />
<input type="button" onclick="sayHello();" value="Say Hello" />
</body>
</html>
它将产生以下输出-
Web Workers是什么?
可以使用 Web Workers 处理上述情况,他们将执行所有计算量大的任务,而不会中断用户界面,并且通常在单独的线程上运行。
Web Workers允许长时间运行的脚本不会被响应单击或其他用户交互的脚本中断,并允许执行长任务而不会产生使页面保持响应的状态。
在Web Worker中执行脚本时,它无法访问网页的窗口对象(window.document),这意味着Web Worker无法直接访问网页和DOM API。尽管Web Workers不能阻止浏览器UI,但是他们仍然可以消耗CPU周期并降低系统响应速度。
Web Workers如何工作?
Web Workers使用JavaScript文件的URL初始化,其中包含该Worker将执行的代码。此代码设置事件侦听器并与从主页派生事件的脚本进行通信。
var worker=new Worker(bigLoop.js);
如果指定的javascript文件存在,浏览器将产生一个新的工作线程,该线程异步下载。
如果您的应用程序具有多个支持的JavaScript文件,则可以将其导入 importScripts()方法,该方法将文件名作为参数,并以逗号分隔,如下所示-
importScripts("helper.js", "anotherHelper.js");
生成Web Worker后,将使用 postMessage()方法完成Web Worker及其父页面之间的通信。根据您的浏览器版本,postMessage()可以接受字符串或JSON对象作为其单个参数。
通过使用主页中的 onmessage 事件访问由Web Worker传递的消息。现在,让无涯教程使用Web Worker编写bigLoop示例。以下是主页(hello.htm),它将产生一个Web工作者来执行循环并返回变量 j 的最终值-
<!DOCTYPE HTML>
<html>
<head>
<title>Big for loop</title>
</span><span class="tag"><script></span><span class="pln">
</span><span class="kwd">var</span><span class="pln"> worker</span><span class="pun">=</span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Worker</span><span class="pun">(</span><span class="str">bigLoop.js</span><span class="pun">);</span><span class="pln">
worker</span><span class="pun">.</span><span class="pln">onmessage</span><span class="pun">=</span><span class="kwd">function</span><span class="pln"> </span><span class="pun">(</span><span class="pln">event</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
alert</span><span class="pun">(</span><span class="str">"Completed "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">data </span><span class="pun">+</span><span class="pln"> </span><span class="str">"iterations"</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">function</span><span class="pln"> sayHello</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
alert</span><span class="pun">(</span><span class="str">"Hello sir...."</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="tag"></script></span><span class="pln">
</head>
<body>
<input type="button" onclick="sayHello();" value="Say Hello"/>
</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 Workers处理错误
下面显示了Web Worker JavaScript文件中的错误处理函数示例,该函数将错误记录到控制台。使用错误处理代码,上面的示例将如下所示-
<!DOCTYPE HTML>
<html>
<head>
<title>Big for loop</title>
</span><span class="tag"><script></span><span class="pln">
</span><span class="kwd">var</span><span class="pln"> worker</span><span class="pun">=</span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Worker</span><span class="pun">(</span><span class="str">bigLoop.js</span><span class="pun">);</span><span class="pln">
worker</span><span class="pun">.</span><span class="pln">onmessage</span><span class="pun">=</span><span class="kwd">function</span><span class="pln"> </span><span class="pun">(</span><span class="pln">event</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
alert</span><span class="pun">(</span><span class="str">"Completed "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> event</span><span class="pun">.</span><span class="pln">data </span><span class="pun">+</span><span class="pln"> </span><span class="str">"iterations"</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
worker</span><span class="pun">.</span><span class="pln">onerror</span><span class="pun">=</span><span class="kwd">function</span><span class="pln"> </span><span class="pun">(</span><span class="pln">event</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="pln">event</span><span class="pun">.</span><span class="pln">message</span><span class="pun">,</span><span class="pln"> event</span><span class="pun">);</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">function</span><span class="pln"> sayHello</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
alert</span><span class="pun">(</span><span class="str">"Hello sir...."</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="tag"></script></span><span class="pln">
</head>
<body>
<input type="button" onclick="sayHello();" value="Say Hello"/>
</body>
</html>
检查浏览器支持
以下是检测浏览器中可用的Web Worker函数支持的语法-
<!DOCTYPE HTML>
<html>
<head>
<title>Big for loop</title>
<script src="/js/modernizr-1.5.min.js"></script>
</span><span class="tag"><script></span><span class="pln">
</span><span class="kwd">function</span><span class="pln"> myFunction</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Modernizr</span><span class="pun">.</span><span class="pln">webworkers</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
alert</span><span class="pun">(</span><span class="str">"Congratulation!! you have web workers support."</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
alert</span><span class="pun">(</span><span class="str">"Sorry!! you do not have web workers support."</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="tag"></script></span><span class="pln">
</head>
<body>
<button onclick="myFunction()">Click me</button>
</body>
</html>
这将产生以下输出-