防止 Service Worker 自动停止
Prevent Service Worker from automatically stopping
Service Worker 似乎在某个时候自动停止。此行为无意中关闭了在激活时建立的 WebSocket 连接。
它什么时候停止,为什么停止?我如何以编程方式禁用此意外操作以使 Service Worker 保持 运行?
您看到的是预期行为,不太可能改变。
Service workers 故意让寿命很短。他们"born"响应特定事件(install
、activate
、message
、fetch
、push
等),执行他们的任务,然后不久之后 "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 活动的良好间隔,但它可能会改变你,你应该试验看看.
Service Worker 似乎在某个时候自动停止。此行为无意中关闭了在激活时建立的 WebSocket 连接。
它什么时候停止,为什么停止?我如何以编程方式禁用此意外操作以使 Service Worker 保持 运行?
您看到的是预期行为,不太可能改变。
Service workers 故意让寿命很短。他们"born"响应特定事件(install
、activate
、message
、fetch
、push
等),执行他们的任务,然后不久之后 "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 活动的良好间隔,但它可能会改变你,你应该试验看看.