HTML5 使用Web Worker处理线程

2016年06月07日 HTML 暂无评论 阅读 12 views 次

基础知识

Web Worker是在HTML5中新增的,用来在Web应用程序中实现后台处理的一项技术。使用这个API,用户可以很容易地创建在后台运行的线程(在HTML5中称为worker),如果将可能耗费较长时间的处理交给后台去执行,对用户在前台页面中执行的操作就完全没有影响了。

创建后台线程的步骤很简单。只要在Worker类的构造器中将需要在后台线程中执行的脚本文件的URL作为参数,然后创建Worker对象就可以了,例如:

Js代码  收藏代码
  1. var worker = new Worker("worker.js");

注意:在后台线程中是不能访问页面或窗口对象的。 如果在后台线程的脚本文件中使用到window对象或document对象,则会引起错误的发生。

另外,可以通过发送和接收消息来与后台线程互相传递数据。通过对Worker对象的message事件句柄的获取可以在后台线程之中接收消息,使用方法如下:

Js代码  收藏代码
  1. worker.addEventListener("message"function(event) {
  2.     // 处理接收的消息。
  3. }, false);

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

Js代码  收藏代码
  1. worker.postMessage(message);

另外,同样可以通过获取Worker对象的message事件句柄及Worker对象的postMessage()方法在后台线程内部进行消息的接收和发送。

与线程进行数据的交互

使用后台线程时不能访问页面或窗口对象,但是并不代表后台线程不能与页面之间进行数据交互。示例中页面上随机生成一个整数数组,然后将该整数数组传入线程,挑选出数组中可以被3整除的数字,然后显示在页面的表格中,主页面代码如下:

Html代码  收藏代码
  1. <!DOCTYPE html>
  2. <html lang="zh-cn">
  3.     <head>
  4.         <meta charset="UTF-8"/>
  5.         <title>与线程进行数据交互</title>
  6.         <script type="text/javascript" src="http://code.jquery.com/jquery-1.6.4.min.js"></script>
  7.         <script type="text/javascript">
  8. $(function() {
  9.     var intArray = new Array(100);
  10.     for(var index = 0; index < intArray.length; index++) {
  11.         intArray[index] = parseInt(Math.random() * 100);
  12.     }
  13.     var worker = new Worker("sumWorker.js");
  14.     worker.postMessage(JSON.stringify(intArray));
  15.     worker.addEventListener("message", function(event) {
  16.         if(event.data != "") {
  17.             var array = JSON.parse(event.data);
  18.             var row, col;
  19.             for(var index = 0; index < array.length; index++) {
  20.                 row = parseInt(index / 10);
  21.                 col = index % 10;
  22.                 if(col == 0) {
  23.                     $("<tr>").appendTo("tbody");
  24.                 }
  25.                 $("<td>").text(array[row * 10 + col]).appendTo("tbody tr:last");
  26.             }
  27.         }
  28.     }, false);
  29. });
  30.         </script>
  31.     </head>
  32.     <body>
  33.         <table>
  34.             <caption>从随机生成的数字中抽取3的倍数并显示</caption>
  35.             <tbody></tbody>
  36.         </table>
  37.     </body>
  38. </html>

示例中使用的线程脚本代码如下:

Js代码  收藏代码
  1. self.addEventListener("message"function(event) {
  2.     var data = JSON.parse(event.data);
  3.     var returnArray = new Array();
  4.     var temp;
  5.     for(var index = 0; index < data.length; index++) {
  6.         if((temp = data[index]) % 3 == 0) {
  7.             returnArray.push(temp);
  8.         }
  9.     }
  10.     self.postMessage(JSON.stringify(returnArray));
  11. }, false);

线程嵌套

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

单层嵌套

修改上例中的主页面script元素中的JavaScript代码如下:

Js代码  收藏代码
  1. $(function() {
  2.     var worker = new Worker("randomWorker.js");
  3.     worker.postMessage("");
  4.     worker.addEventListener("message"function(event) {
  5.         if(event.data != "") {
  6.             var array = JSON.parse(event.data);
  7.             var row, col;
  8.             for(var index = 0; index < array.length; index++) {
  9.                 row = parseInt(index / 10);
  10.                 col = index % 10;
  11.                 if(col == 0) {
  12.                     $("<tr>").appendTo("tbody");
  13.                 }
  14.                 $("<td>").text(array[row * 10 + col]).appendTo("tbody tr:last");
  15.             }
  16.         }
  17.     }, false);
  18. });

其中“randomWorker.js” 脚本文本代码如下:

Js代码  收藏代码
  1. self.addEventListener("message"function(event) {
  2.     var intArray = new Array(100);
  3.     for(var index = 0; index < intArray.length; index++) {
  4.         intArray[index] = parseInt(Math.random() * 100);
  5.     }
  6.     var worker = new Worker("sumWorker.js");
  7.     // 把随机数组传递给子线程进行挑选工作。
  8.     worker.postMessage(JSON.stringify(intArray));
  9.     worker.addEventListener("message"function(event1) {
  10.         self.postMessage(event1.data);  // 把挑选结果返回主页面。
  11.     }, false);
  12. }, false);

注意:在线程,向子线程提交消息时使用子线程对象的postMessage()方法,而向本线程的创建源发送消息时使用self.postMessage()方法。 在本线程中创建的挑选线程“sumWorker.js”脚本代码如下:

Js代码  收藏代码
  1. self.addEventListener("message"function(event) {
  2.     var data = JSON.parse(event.data);
  3.     var returnArray = new Array();
  4.     var temp;
  5.     for(var index = 0; index < data.length; index++) {
  6.         if((temp = data[index]) % 3 == 0) {
  7.             returnArray.push(temp);
  8.         }
  9.     }
  10.     self.postMessage(JSON.stringify(returnArray));
  11.         self.close();  // 关闭子线程。
  12. }, false);

注意:在子线程中向发送源发送回消息后,如果该子线程不再使用,则可以使用self.close()方法关闭该子线程。

多层嵌套

要实现子线程与子线程之间的数据交互,其基本步骤如下:

  1. 先创建发送数据的子线程。
  2. 执行子线程中的任务,然后把要传递的数据发送给主线程。
  3. 在主线程接收到子线程传回来的消息时,创建接收数据的子线程,然后再把发送数据的子线程中返回的消息传递给接收数据的子线程。
  4. 执行接收数据子线程中的代码。

线程中可用的变量、函数与类

给我留言

您必须 登录 才能发表留言!