什么是WebWorker?

         WebWorker是HTML5提供的一种浏览器内置的多线程解决方案,通过JavaScript API来创建一个独立于主线程(也就是UI线程)并且可与其并行运行的工作线程。这个新创建的线程可以执行一些长时间运行的计算密集型任务,从而不会阻塞主线程的执行。

        众所周知,js最初设计是运行在浏览器中的,为了防止多个线程同时操作DOM,带来渲染冲突问题,所以js执行器被设计成单线程。但随着前端技术的发展,js能力远不止如此,当我们遇到需要大量计算的场景时(比如图像处理、视频解码等),js线程往往会被长时间阻塞,甚至造成页面卡顿,影响用户体验。为了解决单线程带来的这一弊端,Web Worker 应运而生。 

通过使用WebWorker,可以享受到如下优点:

  1. 提高程序的响应速度: WebWorker将代码运行在自己分离出来的线程上,可以避免单线程模式下计算密集型任务造成的UI卡顿问题,提高了程序的响应速度。
  2. 充分利用多CPU核心:现代电脑普遍具有多个CPU核心,而WebWorker可以比较简单地实现多线程并行处理,充分利用这些CPU核心,提高程序的执行效率。
  3. 更好的代码结构和模块化:可以将代码分为主线程和工作线程,使代码结构更加合理,同时可以实现更好的项目组织和模块化管理。

需要注意的是,由于WebWorker运行在独立的线程中,因此无法访问DOM,也不能与主线程共享数据,但是它却可以通过postMessage()方法和主线程进行通信,从而实现数据共享和传输。

WebWorker --使用 

使用说明:

  • 同源限制

分配给 worker 线程的脚本,必须和主线程脚本同源。(否则无法创建 worker,且双方无法通信)

  • DOM限制

Worker 工作在子线程,和主线程不太一样。所以并无法操作 DOM \ BOM 等 API。(纯数据处理)

  • 全局对象限制

Worker 全局对象不是 window,所以一些 window 上的全局属性和方法也无法访问。(但可以访问 NavigatorLocation接口)

  • 通信限制

由于 Worker 单独运行在一个子线程,所以和主线程通信使用发布、订阅的消息机制完成。

  • 脚本限制

可以在 Worker 中使用 XMLHttpRequest 来发送异步请求。

  • 运行环境限制

Worker 不能运行在 file:// 协议下。(不能直接右键打开)

 使用WebWorker非常简单,主要包括以下步骤:

  1. 创建一个新的JavaScript文件,用于编写WebWorker的代码,并在其中编写需要运行的长时间计算(通常是没有依赖关系的独立函数)。
  2. 在主线程中创建一个WebWorker对象,并指定包含WebWorker代码的JavaScript文件路径。
const myWorker = new Worker("worker.js");
  1. 使用Worker对象的postMessage()方法向工作线程发送数据。工作线程可以通过onmessage事件监听来接收从主线程传递过来的数据。
// 向工作线程发送消息
myWorker.postMessage(data);

// 在工作线程中监听由主线程发来的消息
self.addEventListener('message', (event) => {
  const data = event.data;
  // 对接收到的数据进行处理...
  postMessage(result);
});
  1. 在工作线程中使用postMessage()方法将计算结果发送回主线程,并使用主线程上的onmessage事件进行监听。
// 在工作线程中发送消息给主线程
postMessage(result);

// 在主线程中监听由工作线程返回的计算结果
myWorker.onmessage = function(event) {
    console.log("Result: " + event.data);
};
  1. 最后,记得在不需要WebWorker时,通过terminate()方法及时结束该Worker对象,以释放资源。
// 终止一个Worker对象
myWorker.terminate();

        需要注意的是,由于WebWorker无法访问DOM对象,在编写工作线程代码时,不能使用window、document等相关对象。

        在Web Worker中,也可以使用importScripts()方法导入其他JavaScript文件,以便使用其中的函数和变量。

        总的来说,Web Worker使得JavaScript能够在后台线程中运行代码,避免了页面的阻塞,提高了用户体验。