Service Worker 和 Shared Worker 有什么区别?
我什么时候应该使用 Service Worker 而不是 Shared Worker,反之亦然?
Service Worker 和 Shared Worker 有什么区别?
我什么时候应该使用 Service Worker 而不是 Shared Worker,反之亦然?
Service Worker 具有共享 Worker 之外的其他功能,并且一旦注册,它们就会在给定网页的生命周期之外持续存在。
服务工作者可以响应message
事件,例如共享工作者,但他们也可以访问其他事件。处理fetch
事件允许服务工作者拦截任何网络流量(源自受控页面)并采取特定操作,包括从Request
/Response
缓存提供响应。还计划向服务人员公开一个push
事件,允许 Web 应用程序在“后台”接收推送消息。
另一个主要区别与持久性有关。一旦为特定来源和范围注册了服务工作者,它就会无限期地保持注册状态。(如果底层脚本发生变化,Service Worker 将自动更新,它可以手动或以编程方式删除,但这是例外。)因为 Service Worker 是持久的,并且其生命周期独立于 Web 浏览器中的活动页面,它为使用它们为上述推送消息提供动力之类的事情打开了大门——push
只要浏览器正在运行,服务工作者就可以“唤醒”并处理事件,而不管哪些页面处于活动状态。未来的 Web 平台功能也可能会利用这种持久性。
还有其他技术差异,但从更高层次的角度来看,这些差异才是最突出的。
SharedWorker上下文是一个有状态的会话,旨在通过异步消息传递(客户端/服务器范式)将网页多路复用到单个应用程序中。它的生命周期是基于域的,而不是像DedicatedWorker(两层范式)那样基于单页。
ServiceWorker上下文被设计为无状态的。它实际上根本不是一个持久会话——它是控制反转(IoC) 或基于事件的持久服务范式。它服务于事件,而不是会话。
一个目的是为数据库和其他持久性服务(即云)提供用于长时间运行查询(LRQ) 的并发安全异步事件。线程池在其他语言中的作用正是如此。
例如,如果您的 Web 应用程序对各种云服务执行许多并发安全 LRQ 以填充自身,那么ServiceWorkers就是您想要的。您可以立即执行数十个安全 LRQ,而不会阻碍用户体验。SharedWorkers和DedicatedWorkers不容易处理许多并发的安全 LRQ。此外,一些浏览器不支持SharedWorkers。
也许他们应该改用ServiceWorkers:为清楚起见CloudWorkers,但并非所有服务都是云。
希望这个解释能引导您思考各种 Worker 类型是如何设计为协同工作的。每个都有自己的专长,但共同的目标是减少 DOM 延迟并改善基于 Web 的应用程序的用户体验。
加入一些用于流式传输的WebSockets和用于图形的WebGL ,您可以构建一些像多人控制台游戏一样运行的炙手可热的 Web 应用程序。
2020 11 更新
对于对此讨论感兴趣的任何人的重要细节:WebKit 不SharedWorker
支持(故意删除 ~v6 或其他内容)。
WebKit 团队明确建议在ServiceWorker
任何SharedWorker
可能相关的地方使用。
对于希望将此功能恢复到 WebKit 的社区,请参阅这个(目前尚未解决)问题。
加上以前的好答案。主要区别在于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
})())
上面的代码要求ServiceWorker在作为参数提供给waitUntil的承诺解决之前不会关闭。如果以这种方式同时处理许多消息,ServiceWorker将不会关闭,直到所有承诺都得到解决。
这可以用来无限期地延长ServiceWorker的生命,使其有效地成为SharedWorker。不过,请记住,如果ServiceWorker运行时间过长,浏览器可能会决定强制关闭。