阮大神教程

webwork简介

Worker 线程一旦新建成功,就会始终运行,不会被主线程上的活动(比如用户点击按钮、提交表单)打断。这样有利于随时响应主线程的通信。但是,这也造成了 Worker 比较耗费资源,不应该过度使用,而且一旦使用完毕,就应该关闭。

webwork使用注意事项

  1. 同源限制

    分配给 Worker 线程运行的脚本文件,必须与主线程的脚本文件同源。

  2. DOM 限制

    Worker 线程所在的全局对象,与主线程不一样,无法读取主线程所在网页的 DOM 对象,也无法使用document、window、parent这些对象。但是,Worker 线程可以navigator对象和location对象。

  3. 通信联系

    Worker 线程和主线程不在同一个上下文环境,它们不能直接通信,必须通过消息完成。

  4. 脚本限制

    Worker 线程不能执行alert()方法和confirm()方法,但可以使用 XMLHttpRequest 对象发出 AJAX 请求。

  5. 文件限制

    Worker 线程无法读取本地文件,即不能打开本机的文件系统(file://),它所加载的脚本,必须来自网络。

示例:.html

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8" />
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  6. <title>Document</title>
  7. <script></script>
  8. </head>
  9. <body>
  10. <!--
  11. 1、h5 规范提供了js分现成的实现,取名为:web Workers
  12. 2、相关API
  13. Worker:构造函数,加载分线程执行的js文件
  14. Worker.prototype.onmessage: 用于接收另一个线程的回调函数
  15. Worker.prototype.postMessage: 向另一个线程发送消息
  16. 3、不足
  17. worker内代码不能操作DOM(更新UI)
  18. 不能跨域加载JS
  19. 不是每个浏览器都支持这个新特性
  20. web Workers 是HTML5提供的一个javascript多线程解决方案
  21. 我们可以将一些大计算量的代码交给由web Worker运动而不冻结用户界面
  22. 但是子线程完全受主线程控制,且不得操作DOM。所以这个新标准并没有改变Javascript单线程的本质。
  23. -->
  24. <input type="text" id="input1" placeholder="输入数字" />
  25. <button id="btn1">计算</button>
  26. </body>
  27. <script>
  28. window.onload = function () {
  29. var oInput = document.getElementById("input1");
  30. var oBtn = document.getElementById("btn1");
  31. oBtn.onclick = function () {
  32. //数字太大的话,会让主线程卡死
  33. var worker = new Worker("work2.js");
  34. worker.onmessage = function (event) {
  35. console.log("主线程接收分线程返回的数据:" + event.data);
  36. worker.terminate(); //关闭线程
  37. };
  38. //向分线程发送消息
  39. worker.postMessage(oInput.value);
  40. worker.addEventListener("error", function(event){
  41. console.log(event);
  42. })
  43. //或者
  44. /*
  45. worker.addEventListener('error', function (event) {
  46. // ...
  47. });
  48. */
  49. };
  50. };
  51. //完成任务以后主线程就可以把它关掉了
  52. </script>
  53. </html>

work2.js

  1. function Fibonacci(n) {
  2. if (n <= 1) {
  3. return n;
  4. }
  5. return Fibonacci(n - 1) + Fibonacci(n - 2);
  6. }
  7. // onmessage = function(event){
  8. // var result = event.data;
  9. // //可以通过data拿到我们想要的数据
  10. // postMessage(Fibonacci(result));
  11. // //可以使用下述对象
  12. // // console.log(location);
  13. // // console.log(navigator)
  14. // //不可以使用 alert 等dom操作
  15. // console.log(alert);
  16. // }
  17. //写法1
  18. // self.addEventListener("message", function(event){
  19. // var result = event.data;
  20. // //可以通过data拿到我们想要的数据
  21. // postMessage(Fibonacci(result));
  22. // })
  23. // //写法2
  24. // this.addEventListener("message", function(event){
  25. // var result = event.data;
  26. // //可以通过data拿到我们想要的数据
  27. // postMessage(Fibonacci(result));
  28. // })
  29. //写法3
  30. addEventListener("message", function(event){
  31. var result = event.data;
  32. //可以通过data拿到我们想要的数据
  33. postMessage(Fibonacci(result));
  34. // self.close(); //用于Worker内部关不自身
  35. importScripts('work3.js')
  36. })
  37. //写法4
  38. // onmessage = function(event){
  39. // var result = event.data;
  40. // //可以通过data拿到我们想要的数据
  41. // postMessage(Fibonacci(result));
  42. // //可以使用下述对象
  43. // // console.log(location);
  44. // // console.log(navigator)
  45. // //不可以使用 alert 等dom操作
  46. // console.log(alert);
  47. // }

数据通信

前面说过,主线程与 Worker 之间的通信内容,可以是文本,也可以是对象。需要注意的是,这种通信是拷贝关系,即是传值而不是传址,Worker 对通信内容的修改,不会影响到主线程。事实上,浏览器内部的运行机制是,先将通信内容串行化,然后把串行化后的字符串发给 Worker,后者再将它还原。主线程与 Worker 之间也可以交换二进制数据,比如 File、Blob、ArrayBuffer 等类型,也可以在线程之间发送。下面是一个例子。