`self.Clients.claim()`有什么用?

Bon*_*Oak 14 javascript frontend offline offline-caching service-worker

要注册服务工作者,我可以打电话

navigator.serviceWorker.register('/worker.js')
Run Code Online (Sandbox Code Playgroud)

每次加载页面时都会检查更新版本worker.js.如果找到更新,则在关闭所有页面的选项卡然后重新打开之前,不会使用新工作程序.我读到的解决方案是:

self.addEventListener('install', function(event) {
  event.waitUntil(self.skipWaiting());
});
self.addEventListener('activate', function(event) {
  event.waitUntil(self.clients.claim());
});
Run Code Online (Sandbox Code Playgroud)

我可以理解skipWaiting部分,但到底是做clients.claim()什么的?我已经完成了一些简单的测试,即使没有它也似乎按预期工作.

Mar*_*ark 17

我也很难理解clients.claim,而且所有解释对我来说都没有任何意义,所以希望这个答案也能帮助任何陷入困境的人。

要了解Clients.claim,我们必须查看工作人员生命周期。

  1. 安装;这是注册后的第一阶段。当oninstall处理程序完成时,Service Worker 被视为已安装。
  2. 已安装;Service Worker 正在等待使用其他 Service Worker 的客户端关闭。
  3. 激活;不存在由其他服务人员控制的客户端。当onactive处理程序完成时,Service Worker 被视为已激活。
  4. 已激活;Service Worker 现在控制该页面。

SkipWaitingClients.claim旨在解决不同的问题。

Clients.claim 在您的网页第一次通过注册 Service Worker 从不受控网页变为受控(由 Service Worker)网页时产生影响。

SkipWaiting正是它所说的。它跳过等待阶段并直接进入激活阶段。一旦激活,它现在就成为所有客户端的活动 Service Worker。客户端是在 Service Worker 范围内打开网页的任何窗口或选项卡。


那么为什么我们需要Clients.claim呢?

这让我很困惑,我打赌你也很困惑。答案最好用一个例子来描述。

想象一下,您的网页没有注册服务工作者,因此不受控制。您打开了网页的两个选项卡(客户端)。您对网页进行更新,以便它现在可以注册 Service Worker。

您决定重新加载第一个选项卡(客户端),它现在将获取注册 Service Worker 的脚本并开始安装。安装后,它会注意到没有其他客户端由 Service Worker 控制,因此它不必等待,它可以立即安全地激活 Service Worker,并且任何资源的获取现在都将通过您的 Service Worker。

然而,这里有一个问题,您的其他选项卡(客户端)现在也将有一个活动的服务工作者,但是,它尚未受到控制。这意味着任何获取都不会通过 Service Worker。您需要重新加载任何其他选项卡(客户端)才能使其由活动服务工作人员控制。这很令人困惑,因为如果此后任何新的服务工作人员通过使用skipWaiting强制它变得活跃,其他选项卡(客户端)将立即由新的活动服务工作人员控制。所以我强调只有当不受控制的网页变得受控制时才需要重新加载部分。

输入Clients.claim。当您在第一个 Service Worker 被激活时调用self.clients.claim()时,如下所示:

self.addEventListener('activate', event => {
  event.waitUntil(clients.claim());
});
Run Code Online (Sandbox Code Playgroud)

它将确保不受控制但具有活动 Service Worker 的其他选项卡(客户端)将由活动 Service Worker 控制。这意味着对资源的任何获取现在都将通过活动的 Service Worker。如果没有Clients.claim,则在重新加载页面之前不会使用 Service Worker。

同样,如果所有网页都已由 Service Worker 控制。如果检测到并安装了新的服务工作线程,它通常会等待,直到网页(客户端)的所有选项卡都关闭。下次您访问该网页时,它将激活新的 Service Worker 并且该网页将由它控制。

但是,如果您不关闭所有客户端,并且通过使用skipWaiting强制新的服务工作人员,它将立即对所有客户端变为活动状态并受到控制。这意味着从任何客户端对资源的任何新获取现在都将立即通过您的新服务工作人员。现在,您不需要使用Clients.claim即可让其他客户端开始使用您的新服务工作线程。

这是我的尝试,希望对某人有所帮助。


Jef*_*ick 10

我从服务工作者生命周期指南中摘录了以下内容:

clients.claim

clients.claim()一旦激活,您可以通过在服务人员内部呼叫来控制不受控制的客户端 .

以下是上述演示的变体,其中调用clients.claim()了activate事件.你应该第一次看到一只猫.我说"应该",因为这对时间敏感.如果服务工作者激活并clients.claim()在映像尝试加载之前生效,您将只看到一只猫.

如果您使用服务工作者加载页面的方式与通过网络加载的页面不同,clients.claim()可能会很麻烦,因为您的服务工作者最终会控制一些没有它的客户端.

注意:我看到很多人包括clients.claim()作为样板,但我自己很少这样做.它只对第一次加载非常重要,并且由于渐进式增强,页面通常在没有服务工作者的情况下愉快地工作.

  • 所以我认为`self.skipWaiting()`将用于立即将更新应用于现有的serviceWorker,并且`clients.claim()`将用于在第一次加载时立即获得控制权. (3认同)

Ima*_*eem 5

next page-reload注册后,服务人员从以下位置进行控制。通过使用self.skipWaiting()self.clients.claim(),您可以要求客户端first load自行控制服务工作者。

例如

假设我缓存了文件hello.txt,然后再次hello.txt调用,即使我在缓存中拥有资源,也会进行服务器调用。这是我不使用时的情况self.clients.claim()。但是,hello.txt在下一页重新加载时发出服务器调用时,它将从缓存中提供资源。

为了解决此问题,我必须使用self.skipWaiting()和的组合,self.clients.claim()以便服务工作者在激活内容后立即开始提供内容。

PS:

next page-reload 表示重新访问页面。

first load 表示第一次访问页面的时刻。