Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Web Workers #74

Open
Tracked by #6
swiftwind0405 opened this issue Dec 3, 2020 · 0 comments
Open
Tracked by #6

Web Workers #74

swiftwind0405 opened this issue Dec 3, 2020 · 0 comments

Comments

@swiftwind0405
Copy link
Owner

swiftwind0405 commented Dec 3, 2020

为什么要使用 Web Worker

异步编程的局限性:
当 js 中有一段阻塞的代码(例如一个巨大的循环),没有办法释放 Event Loop 以及使浏览器的界面不被干扰。这意味着异步函数只解决了 js 单线程限制性的很小一部分。

Web workers 允许开发者把长时间运行和密集计算类的任务放在后台运行,这样就不会干扰用户界面,让我们的 web 页面更易响应化。

Web Worker 的作用,就是为 JavaScript 创造多线程环境,允许主线程创建 Worker 线程,将一些任务分配给后者运行。

在主线程运行的同时,Worker 线程在后台运行,两者互不干扰。等到 Worker 线程完成计算任务,再把结果返回给主线程。这样的好处是,可以在独立线程中处理一些计算密集型或高延迟的任务,从而允许主线程(通常是 UI 线程)不会因此被阻塞或拖慢。

![[Pasted image 20201207194228.png]]

Web Workers 作为一个独立的线程运行在浏览器中。因此,它们执行的代码应该在一个独立的文件中。

局限性

「直接在 worker 线程中操纵 DOM 元素,或使用 window 对象中的某些方法和属性。」 大部分 window 对象的方法和属性是可以使用的,包括 WebSockets,以及诸如 IndexedDB 和 FireFox OS 中独有的 Data Store API 这一类数据存储机制。

主线程与 Web Workers 之间的通信

workers 和主线程间的数据传递通过这样的消息机制进行——双方都使用postMessage() 方法发送各自的消息,使用 onmessage 事件处理函数来响应消息(消息被包含在 Message 事件的 data 属性中)。这个过程中数据并不是被共享而是被复制

![[Pasted image 20201207194418.png]]

除此之外,Worker 还可以通过 XMLHttpRequest 来访问网络,只不过 XMLHttpRequest 对象的 responseXMLchannel 这两个属性的值将总是 null。

Web Workers 的类型

Web Worker 规范中定义了两类工作线程,分别是专用线程 Dedicated Worker 和共享线程 Shared Worker,其中,Dedicated Worker 只能为一个页面所使用,而 Shared Worker 则可以被多个页面所共享。

专用 worker(Dedicated workers)

一个专用 worker 仅仅能被生成它的脚本所使用。

在主线程中使用时,onmessagepostMessage() 必须挂在 worker 对象上,而在 worker 中使用时不用这样做。原因是,在 worker 内部,worker 是有效的全局作用域。

var myWorker = new Worker('worker.js');

使用案例参考这个:Dedicated Workers basic example

需要注意的是,由于 Web Worker 有同源限制,所以在进行本地调试或运行以下示例的时候,需要先启动本地服务器,直接使用 file:// 协议打开页面的时候,会抛出以下异常:

共享 worker(Shared workers)

一个共享 Worker 是一种特殊类型的 Worker,可以被多个浏览上下文访问,比如多个 windows,iframes 和 workers,但这些浏览上下文必须同源。相比 dedicated workers,它们拥有不同的作用域。
生成一个新的共享 worker 与生成一个专用 worker 非常相似,只是构造器的名字不同:

var myWorker = new SharedWorker('worker.js');

一个非常大的区别在于,与一个共享 worker 通信必须通过端口对象——一个确切的打开的端口供脚本与 worker 通信(在专用 worker 中这一部分是隐式进行的)。

使用案例参考这个:Shared Workers basic example

调试 Shared Workers

在实际项目开发过程中,若需要调试 Shared Workers 中的脚本,可以通过 chrome://inspect 来进行调试,具体步骤如下图所示:
![[Pasted image 20201214161812.png]]

嵌入式 worker(Embedded workers)

服务 worker(Service workers)

Service workers 本质上充当 Web 应用程序与浏览器之间的代理服务器,也可以在网络可用时作为浏览器和网络间的代理。它们旨在(除其他之外)使得能够创建有效的离线体验,拦截网络请求并基于网络是否可用以及更新的资源是否驻留在服务器上来采取适当的动作。

终止 worker 的两种方法

  • 主进程中终止:myWorker.terminate()
  • worker 内自己终止:close()

Web Workers 的通信

在主页面与 worker 之间传递的数据是通过拷贝,而不是共享来完成的。传递给 worker 的对象需要经过序列化,接下来在另一端还需要反序列化。页面与 worker 不会共享同一个实例,最终的结果就是在每次通信结束时生成了数据的一个副本。大部分浏览器使用结构化拷贝来实现该特性。

postMessage

参考资料

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant