防止 Service Worker 自动停止

Prevent Service Worker from automatically stopping

Service Worker 似乎在某个时候自动停止。此行为无意中关闭了在激活时建立的 WebSocket 连接。

它什么时候停止,为什么停止?我如何以编程方式禁用此意外操作以使 Service Worker 保持 运行?

您看到的是预期行为,不太可能改变。

Service workers 故意让寿命很短。他们"born"响应特定事件(installactivatemessagefetchpush等),执行他们的任务,然后不久之后 "die"。生命周期通常足够长,可以在 worker 死亡之前处理多个事件(即 install 之后可能是 activate 之后是 fetch),但它最终会死亡。这就是为什么不要依赖脚本中的任何全局状态,并且在服务工作者启动时 bootstrap 通过 IndexedDB 或缓存存储 API 需要的任何状态信息是非常重要的。

Service Worker 是有效的后台进程,每当您访问某些网页时就会安装这些进程。如果允许这些后台进程 运行 无限期地运行,那么对 device/computer 的电池和性能产生负面影响的风险就会增加。为了减轻这种风险,您的浏览器只会在知道有必要时才 运行 这些进程,即响应事件。

WebSockets 的一个用例是让您的客户端监听来自服务器的一些数据。对于该用例,使用 WebSockets 的 service worker 友好替代方法是使用 Push Messaging API 并让您的 service worker 响应 push 事件。请注意,在当前的 Chrome 实现中,您必须在处理 push 事件时显示用户可见的通知。目前不支持 "silent" push 用例。

如果您不是从服务器监听数据,而是使用 WebSockets 作为从客户端向服务器发送数据的方式,不幸的是没有对服务工作者友好的好方法。在未来的某个时候,可能有一种方法可以注册你的服务工作者通过 periodic/time-based 事件唤醒,此时你可以使用 fetch() 将数据发送到服务器,但这是目前不支持任何浏览器。

P.S.: Chrome(通常)在您打开 DevTools 界面时不会杀死 Service Worker,但这只是为了简化调试,而不是实际应用程序应依赖的行为。

理论

理论部分 - 为什么以及如何详细介绍。

它还包括许多关于您可能不想继续这样做的原因的要点。

但是,就我而言,缺点是不存在的,因为我的应用程序将 运行 在仅保留给 运行 我的应用程序的台式机上。但是即使浏览器 window 最小化,我也需要保持 SW 处于活动状态。因此,如果您正在开发一个将 运行 在各种设备上运行的网络应用程序,那么保持 SW 活动可能不是一个好主意,因为上面的答案中讨论了这些内容。

话虽如此,让我们转向实际、实用的答案。

我的“实用”解决方案

应该有很多方法可以让 SW 保持活动状态,因为 SW 在响应许多不同的事件后会保持活动状态。在我的例子中,我将一个虚拟文件放到服务器上,将其缓存在 SW 中,并定期从 document.

请求该文件

因此步骤是;

  • 在服务器上创建一个虚拟文件,比如 ping.txt
  • 在您的 SW 上缓存文件
  • 定期从您的 html 请求该文件以保持 SW

例子

// in index.html
setInterval(function(){
    fetch('/ping.txt')
}, 20000)

请求实际上不会到达服务器,因为它会缓存在 SW 上。尽管如此,这将使 SW 保持活动状态,因为它会响应 fetch 甚至由请求引发。

PS: 我发现 20 秒是保持 SW 活动的良好间隔,但它可能会改变你,你应该试验看看.