简介
Web Worker 的作用,就是为 JavaScript 创造多线程环境,允许主线程创建 Worker 线程,将一些任务分配给后者运行。在主线程运行的同时,Worker 线程在后台运行,两者互不干扰。
等到 Worker 线程完成计算任务,再把结果返回给主线程。这样的好处是,一些计算密集型或高延迟的任务,被 Worker 线程负担了,主线程(通常负责 UI 交互)就会很流畅,不会被阻塞或拖慢
使用限制
- 同源限制
分配给 Worker 线程运行的脚本文件,必须与主线程的脚本文件同源
- DOM 限制
Worker 线程所在的全局对象,与主线程不一样,无法读取主线程所在网页的 DOM 对象,也无法使用 document、window、parent
这些对象。但是,Worker 线程可以 navigator
对象和 location
对象。
- 通信联系
Worker 线程和主线程不在同一个上下文环境,它们不能直接通信,必须通过消息完成
- 脚本限制
不能执行 alert()
方法和 confirm()
方法,但可以使用 XMLHttpRequest 对象发出 AJAX 请求
- 文件限制
Worker 线程无法读取本地文件,即不能打开本机的文件系统(file://
),它所加载的脚本,必须来自网络. 【本地开发使用 localhost】
使用 API
结构:
1 2 3 4 5
| ├── index.html ├── worker-helper │ ├── 1.js │ └── 2.js └── worker.js
|
示例:
worker 中的全局对象是 DedicatedWorkerGlobalScope,可以当作是 不具有 DOM 对象的 Window
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> </head> <body> <input type="file" /> <script> const worker = new Worker("./worker.js", { name: "myWorker" });
worker.onmessage = function (event) { console.log("Received message & Work done!" + event.data);
if (event.data === "close") { worker.terminate(); } }; worker.onerror = function (event) { console.log(`ERROR: Line ${e.lineno} in ${e.filename} : ${e.message}`); }; worker.postMessage("Hello World"); worker.postMessage({ method: "echo", args: ["Work"] });
console.log(worker);
const ab = new ArrayBuffer(100);
worker.postMessage(ab, [ab]);
console.log(ab);
worker.addEventListener("message", function (event) { if (event.data.byteLength) { console.log(event.data); } }); </script>
<script id="worker" type="app/worker"> addEventListener('message', function () { postMessage('some message'); }, false); </script> <script> const blob = new Blob([document.querySelector("#worker").textContent]); const url = window.URL.createObjectURL(blob); const scriptWorker = new Worker(url);
scriptWorker.onmessage = function (e) { }; </script> </body> </html>
|
代码中的 “转移底层” 的概念,也就是 postMessage 的 第二个参数,更多请参考 MDN 文档.
SharedArrayBuffer
类型不能被转移,因为已经被共享,SharedArrayBuffer
允许 Worker
线程与主线程共享同一块内存
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| console.log(this); console.log(`worker name: ${this.name}`); addEventListener( "message", function (e) { console.log(e); postMessage(`You said: ${e.data}`);
if (e.data === "close") { close(); }
if (e.data.byteLength) { postMessage(e.data, [e.data]); console.log("worker buffer", e.data); } }, false );
importScripts("./worker-helper/1.js", "./worker-helper/2.js");
addEventListener("error", function (e) {});
|