Service Worker与Shared Worker的区别

48

Service Worker和Shared Worker有什么区别?

什么情况下应该使用Service Worker而不是Shared Worker,反之亦然?


1
根据规范(截至2015年2月5日的草案),服务工作者是一种Web工作者类型,它响应于从文档和其他来源分派的事件。 - Ray Shan
4个回答

30

服务工作者比共享工作者拥有更多的功能,一旦注册,它们可以在给定网页的生命周期之外持久存在。

服务工作者可以响应message事件,就像共享工作者一样,但它们还可以访问其他事件。处理fetch事件允许服务工作者拦截任何网络流量(源自受控页面),并采取特定操作,包括从Request/Response缓存中提供响应。还有plans计划将push事件暴露给服务工作者,允许Web应用程序在“后台”接收推送消息。

另一个主要的区别与持久性有关。一旦服务工作者为特定的源和范围注册,它将无限期地保持注册状态。(如果底层脚本发生更改,服务工作者将自动更新,并且可以手动或以编程方式删除,但这是例外。)由于服务工作者是持久的,并且具有独立于Web浏览器中活动页面的生命周期,因此它为诸如使用它们来支持前面提到的推送消息等事物打开了大门-只要浏览器正在运行,服务工作者就可以被“唤醒”并处理推送事件,而不管哪些页面处于活动状态。未来的Web平台功能也可能利用这种持久性。还有其他技术差异,但从更高层次的视角来看,以上就是最显著的区别。

12
Service Workers的生命周期很短暂:"开发者需要牢记Service Workers可能会在一秒内被启动和终止多次"。然而,当你说“生命周期”时,可能并不意味着相同的含义。 - Noah Freitas
2
所以,Web Worker 只与页面一起工作,而 Service Worker 的生命周期完全独立于页面?此外,Service Worker 可以访问缓存存储和特殊事件(例如“fetch”)。有什么想法为什么他们创建了新实体?为什么不只是在现有的 Web Worker 中添加一些特殊标志,如“当页面关闭时保持活动状态”,并添加所需的事件和 API? - artin
Service workers不是持久的。它们是请求处理程序 - 每个请求/响应对一个实例。这允许许多并发请求和响应而不会阻塞DOM。即使XHR请求在响应中也会阻塞DOM。这是因为所有工作线程都有自己的上下文/事件循环。 - Dominic Cerisano
1
@NoahFreitas,这不就和SharedWorker一样吗? - Pacerier
2
@Pacerier 这里最相关的区别是,共享工作者的“寿命”是由应用程序通过new SharedWorker和调用该工作者上的terminate方法来编程确定的;而对于服务工作者,浏览器本身决定工作者实例的生命周期以及何时开始,这取决于已注册的事件侦听器。 - Noah Freitas
1
我看到这个答案是5年前的,它还是最新的吗? - Zach Smith

28
SharedWorker上下文是一种有状态的会话并通过异步消息 (客户端/服务器范式)将 Web 页面多路复用到单个应用程序中。它的生命周期是基于域的,而不是像DedicatedWorker一样基于单个页面的(二级范式)。 ServiceWorker上下文被设计为无状态的。它实际上根本不是持久的会话-它是控制反转(IoC)或基于事件的持久性服务范式。它服务于事件,而不是会话。
其中一个目的是为数据库和其他持久性服务(即云)提供并发安全的异步事件,用于长时间运行的查询(LRQs)。就像其他语言中的线程池所做的那样。
例如,如果您的 Web 应用程序执行许多并发安全的 LRQs 来填充自身到各种云服务中,那么ServiceWorkers正是您需要的。您可以立即执行数十个安全的LRQs,而不会阻塞用户体验。而SharedWorkersDedicatedWorkers则不易处理许多并发安全的LRQs。此外,某些浏览器不支持SharedWorkers
或许他们应该使用更清晰的名称,如CloudWorkers,但并非所有服务都是云服务。
希望这个解释能让您思考各种 Worker 类型是如何被设计来共同工作的。每个都有其专业化,但共同的目标是减少 DOM 的延迟并改善基于 Web 的应用程序的用户体验。
加入一些WebSockets进行流式传输和WebGL进行图形处理,您就可以构建一些性能像多人游戏机控制台游戏的炫酷 Web 应用程序了。

1
他们应该把“ServiceWorkers”称为后台工作者。 - Pacerier
4
所有工作人员都是后台工作者-这就是他们的目的,将工作从前台(DOM)线程中推出。 - Dominic Cerisano

6

2022年06月更新

WebKit最近增加了对SharedWorker的支持,有关解决方案的详细信息,请参见下面提到的问题链接。

2020年11月更新

对于任何对此讨论感兴趣的人来说,一个重要的细节是:SharedWorker不被WebKit支持(在v6左右被故意删除了)。

WebKit团队明确建议在可能涉及到SharedWorker的地方使用ServiceWorker

对于社区希望将此功能恢复到WebKit中的人,请参见(目前未解决)问题。


似乎有误 - MDN文档中没有提到SharedWorker,而caniuse显示它们是受支持的:https://caniuse.com/?search=SharedWorker - Dmitry Gonchar
好的,写这篇文章时还没有错,WebKit在2022年中开始支持它,我会更新答案,谢谢。 - GullerYA

2

除了之前的优秀回答外,需要补充说明的是ServiceWorkerSharedWorker的主要区别在于ServiceWorker是无状态的(会关闭并在全局范围内重新启动),而SharedWorker将在会话期间保持状态。

但是,仍然有可能请求ServiceWorker在消息处理程序的持续时间内保持状态。

s.onmessage = e => e.waitUntil((async () => {
  // do things here
  // for example issue a fetch and store result in IndexedDb
  // ServiceWorker will live till that promise resolves
})())

上述代码要求在参数传递给waitUntil的承诺解决之前,ServiceWorker不会关闭。如果许多消息以这种方式同时处理,ServiceWorker将不会关闭,直到所有承诺都得到解决。
这可能被用于无限期延长ServiceWorker的生命周期,使其有效地成为一个SharedWorker。但请记住,如果ServiceWorker运行时间过长,浏览器可能会强制关闭它。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接