基础知识

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

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



HTML5 使用Web Worker处理线程_json



1. var worker = new Worker("worker.js");



注意:在后台线程中是不能访问页面或窗口对象的。

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



HTML5 使用Web Worker处理线程_json


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


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



HTML5 使用Web Worker处理线程_json



    1. worker.postMessage(message);



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

    与线程进行数据的交互

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



    HTML5 使用Web Worker处理线程_json



      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. intArray = new
      10. index = 0; index < intArray.length; index++) {  
      11.         intArray[index] = parseInt(Math.random() * 100);  
      12.     }  
      13. worker = new
      14.     worker.postMessage(JSON.stringify(intArray));  
      15.     worker.addEventListener("message", function(event) {  
      16.         if(event.data != "") {  
      17. array = JSON.parse(event.data);  
      18.             var row, col;  
      19. index = 0; index < array.length; index++) {  
      20. row = parseInt(index / 10);  
      21. col = index
      22. col
      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>


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



      HTML5 使用Web Worker处理线程_json


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


      线程嵌套

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

      单层嵌套

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



      HTML5 使用Web Worker处理线程_json


      1. $(function() {  
      2. var worker = new Worker("randomWorker.js");  
      3. "");  
      4. "message", function(event) {  
      5. if(event.data != "") {  
      6. var
      7. var
      8. for(var
      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” 脚本文本代码如下:



      HTML5 使用Web Worker处理线程_json

      1. self.addEventListener("message", function(event) {  
      2. var intArray = new
      3. for(var
      4.         intArray[index] = parseInt(Math.random() * 100);  
      5.     }  
      6. var worker = new Worker("sumWorker.js");  
      7. // 把随机数组传递给子线程进行挑选工作。
      8.     worker.postMessage(JSON.stringify(intArray));  
      9. "message", function(event1) {  
      10. // 把挑选结果返回主页面。
      11. false);  
      12. }, false);  
       
       
      注意:在线程,向子线程提交消息时使用子线程对象的postMessage()方法,而向本线程的创建源发送消息时使用self.postMessage()方法。
       
       
       
        
      1. self.addEventListener("message", function(event) {  
      2. var
      3. var returnArray = new
      4. var
      5. for(var
      6. if((temp = data[index]) % 3 == 0) {  
      7.             returnArray.push(temp);  
      8.         }  
      9.     }  
      10.     self.postMessage(JSON.stringify(returnArray));  
      11. // 关闭子线程。
      12. }, false);



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

      多层嵌套

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

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

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

      • self:用来表示本线程范围内的作用域。
      • postMessage(msg):向创建线程的源窗口发送消息。
      • onmessage:获取接收消息的事件句柄。
      • importScripts(urls):导入其它JavaScript脚本文件。参数为该脚本文件的URL地址,可以导入多个脚本文件,导入的脚本文件必须与使用该线程文件的页面在同一个域中,并在同一个端口中。
      • navigator对象:与window.navigator对象类似,具有appName、platform、userAgent、appVersion等属性。
      • sessionStorage、localStorage:可以在线程中使用Web Storage。
      • XMLHttpRequest:可以在线程中处理Ajax请求。
      • Web Workers:可以在线程中嵌套线程。
      • setTimeout()、setInterval():可以在线程中实现定时处理。
      • close():结束本线程。
      • eval()、isNaN()、escape()等:可以使用所有JavaScript核心函数。
      • object:可以创建和使用本地对象。
      • WebSockets:可以使用WebSockets API来向服务器发送和接收信息。