首页 >web前端 >js教程 >开始之前您需要了解的有关 Web Worker 的所有信息。

开始之前您需要了解的有关 Web Worker 的所有信息。

DDD
DDD原创
2024-10-31 21:07:291012浏览

最近我一直在研究 Web Worker,这是一份全面的指南,涵盖了开始使用 Web Worker 所需了解的所有内容。

如果您想跳过阅读博客并查看代码,这里是包含所有代码片段的 github 存储库。

Github Web Worker 存储库

 

目录

  • 常见误解
  • Web Worker 基本设置
    • 使用本机 JavaScript 设置 Web Worker
    • 使用 Comlink 设置 Web Workers
  • 如何检查我的工人是否已正确注册?
  • 延伸阅读

 
 

常见的误解

所以,促使我探索 Web Workers 的原因是,在我构建的平台中,一项计算繁重的任务会阻塞 UI。
所以我想,‘嗯,好吧,我该如何让它不阻塞 UI’?我是否应该使用 setTimeout 来确保主线程中的所有代码都已执行完毕,然后才能运行计算量大的任务?

所以这是一个误解——使用setTimeout并不意味着UI不会被阻塞。是的,主线程上的所有内容都将在 setTimeout 回调运行之前执行,但是,当该回调从宏任务队列中弹出时,它会在主线程本身中运行,从而使 UI 无响应。

要了解更多有关 setTimeout 如何工作的信息,请参考一些参考资料 —

  • 从头开始的异步 JavaScript 和事件循环 - Akshay Saini
  • 事件循环、Web API、任务队列 - Lydia Hallie

 
 

Web Worker 基本设置

JavaScript 本质上是一种“单线程语言”,但是 Web Worker 使我们能够在单独的线程中运行计算量大的代码。

在开始之前,有几件事需要注意 -

  • Web Worker 无法与 DOM 交互
  • Web Worker 作用域是 self,而不是 window。
  • Workers 相对较重,不适合大量使用。例如,为四兆像素图像的每个像素启动一名工作人员是不合适的。 [参考 - HTML 规范]
  • 此外,Web Worker 并不是要让某件事需要 2 秒而不是 4 秒,而是要在 DOM 冻结 0 秒的情况下完成这件事。 [参考 - Web Workers 很慢,没关系 - Calvin Metcalf]
  • 工作人员可能会产生新的工作人员,只要这些工作人员托管在与父页面相同的源中。 [参考 - MDN]

 

使用原生 JavaScript 的 Web Worker

  1. 创建一个新的 JavaScript 文件,其中包含要在工作线程中运行的代码。 (比如worker.js)
  2. 在主脚本中实例化worker -
const worker = new Worker("./worker.js")

注意:worker.js 不是一个模块,不能使用 import 语句。然而。 :')

要将worker.js用作模块,请在构造函数的选项中指定type: module。

const worker = new Worker("./worker.js")
  1. 数据通过消息系统在工作人员之间发送 - 双方都使用 postMessage() 方法发送消息,并通过 onmessage 事件处理程序响应消息
  2. 要在 postMessage() 中传递具有循环引用的复杂对象,请使用 StructuredClone 方法。
  3. 要终止 Web Worker,请使用 Worker API 的终止方法。这并不为工人提供完成其正在进行的操作的机会;它立即停止。
const worker = new Worker('./worker.js', { type: 'module' })

 
把它们放在一起

现在,让我们看看集成 Web Worker 后我们的代码是什么样子。

主线程代码:

worker.terminate() 

工作线程代码:

// ...
function workerFunction() {
  // Don't spin up a new worker instance if the process has already been started.
  if (statusElement.textContent !== PROCESS_STATUS.PROCESSING && window.Worker) {
    const worker = new Worker('./worker.js', {
      type: 'module'
    })

    // Sending 10000000000000 to the web worker
    worker.postMessage(10000000000000)

    statusElement.textContent = PROCESS_STATUS.PROCESSING

    // This piece of code is executed after worker finishes its task and returns data. 
    worker.onmessage = function (event) {
      statusElement.textContent = event.data
    }
  }
}
// ...

结果:

当我们运行应用程序时,您会注意到执行计算量大的任务时不会阻塞 UI。

 

使用 Comlink 设置 Web Worker

Comlink 是一个小型库(1.1kB),它消除了思考 postMessage 逻辑的心理障碍。

在更抽象的层面上,它是 postMessage 和 ES6 代理的 RPC 实现。

我使用 Comlink 的一个具体原因是我无法使用纯 JavaScript 将函数从主线程传递到工作线程。使用 Comlink 的代理,我能够轻松地将回调函数从主线程传递到工作线程。 [参考此部分]

要开始在项目中使用 comlink,请安装库

const worker = new Worker("./worker.js")

要开始使用这个库,我们需要了解以下这些方法 -

Comlink.wrap(端点)

  • 包装工作人员公开的对象,返回一个代理,您可以像本地对象一样与之交互。
  • 代理将具有公开值的所有属性和功能,但访问和调用本质上是异步的。即,如果函数返回一个数字,它现在将返回该数字的承诺。
const worker = new Worker('./worker.js', { type: 'module' })

Comlink.expose(值、端点?、allowedOrigins?)

  • 暴露函数将值从一个线程暴露给另一个线程(即将对象从工作线程暴露给主线程)
worker.terminate() 

 

如何检查我的工人是否已正确注册?

  • 检查工作文件是否已在网络浏览器中注册(我使用的是 Chrome)
  • 右键单击→检查,然后转到源面板,您将在其中找到工作文件。
  • 终止后,工作文件不应在“源”面板中可见
  • 如果您在终止工作人员后仍然可以看到工作人员文件,那么很可能您已经注册了多个工作人员,但并非所有工作人员都已被终止。

All you need to know about web workers to get started.

 


延伸阅读
  • 传输处理程序和事件监听器
  • 共享工作者
  • 可转让物品



以上是开始之前您需要了解的有关 Web Worker 的所有信息。的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn