概述

Web Worker 的作用,就是为 JavaScript 创造多线程环境,允许主线程创建 Worker 线程,将一些任务分配给后者运行。在主线程运行的同时,Worker 线程在后台运行,两者互不干扰。等到 Worker 线程完成计算任务,再把结果返回给主线程。这样的好处是,一些计算密集型或高延迟的任务,被 Worker 线程负担了,主线程(通常负责 UI 交互)就会很流畅,不会被阻塞或拖慢。 Worker 线程一旦新建成功,就会始终运行,不会被主线程上的活动(比如用户点击按钮、提交表单)打断。这样有利于随时响应主线程的通信。但是,这也造成了 Worker 比较耗费资源,不应该过度使用,而且一旦使用完毕,就应该关闭。

限制

  1. 同源限制:分配给 Worker 线程运行的脚本文件,必须与主线程的脚本文件同源。
  2. DOM 限制:Worker 线程所在的全局对象,与主线程不一样,无法读取主线程所在网页的 DOM 对象,也无法使用 documentwindowparent 这些对象。但是,Worker 线程可以 navigator 对象和 location 对象。
  3. 通信联系:Worker 线程和主线程不在同一个上下文环境,它们不能直接通信,必须通过消息完成。
  4. 脚本限制:Worker 线程不能执行alert()方法和confirm()方法,但可以使用 XMLHttpRequest 对象发出 AJAX 请求。
  5. 文件限制:Worker 线程无法读取本地文件,即不能打开本机的文件系统(file://),它所加载的脚本,必须来自网络。


基本使用

主线程

  1. // 创建 worker
  2. const worker = new Worker('/worker.js', {
  3. type: 'classic', // 声明 worker.js 是什么模块化类型的文件,类似于 script 的 type
  4. credentials: 'omit', // 用以指定 worker 凭证的 DOMString 值.该值可以是 omit, same-origin,或 include.。如果未指定,或者 type 是 classic,将使用默认值 omit (不要求凭证)。(未研究)
  5. name: 'workerName' // worker 的名称,用于在多个 worker 之间区分
  6. })
  7. // 发送信息
  8. worker.postMessage('message')
  9. // 接收信息
  10. worker.onmessage = function(e){...}
  11. // 子线程内部发生出错
  12. worker.onerror = function(){...}
  13. // 当传送的 message 无法序列化的时候触发
  14. worker.onmessageerror = function(){...}
  15. // 关闭 Worker
  16. worker.terminate()

子线程

  1. // 发送信息给主线程
  2. postMessage('message')
  3. // 接收主线程内容
  4. addEventListener('message', function (e) {
  5. // ...
  6. }, false);
  7. // 引用其他脚本,无返回值
  8. importScripts('otherScript.js')
  9. // 关闭线程
  10. close()

其他使用

同页面 Web Worker

  1. <script id="worker" type="app/worker">
  2. addEventListener('message', function () {
  3. postMessage('some message');
  4. }, false);
  5. </script>
  6. <script>
  7. const blob = new Blob([document.querySelector('#worker').textContent]);
  8. const url = window.URL.createObjectURL(blob);
  9. const worker = new Worker(url);
  10. </script>

参考