共享跨多个服务工作者定义的获取处理程序逻辑

时间:2017-07-22 17:55:54

标签: javascript service-worker offline-caching

关注This Discussion,哪里有评论说明

修补Fetch

  

通过重写self.fetch,self.XMLHttpRequest和self.caches(for   cache.add /中的addAll)?看起来这些可以让你拦截网络请求并在主SW脚本看到之前操纵响应。

我一直在寻找任何有关此类内容的文档,而且似乎找不到任何文档。

在我只是需要 multiple服务工作者共存于一个范围的情况下,

在其中一个中有importScripts后导入另一个的事件处理程序,

我如何修补fetch /避免获取竞争/让两个获取处理程序都工作?

1 个答案:

答案 0 :(得分:11)

这里有几件事要介绍:

单一范围内的多个服务工作者

给定范围只能有一个活动服务工作者。如果您尝试注册两个具有相同范围的不同服务工作者脚本,则第二个注册将触发service worker update flow

// There's an implied default scope of '/'.
// See https://stackoverflow.com/a/33881341/385997
navigator.serviceWorker.register('/sw1.js');

// If called later on, this will trigger the update flow.
// You'll only end up with one of the two being active.
navigator.serviceWorker.register('/sw2.js');

sw2.js何时激活并控制任何现有客户端的确切时间取决于您是否在self.skipWaiting()内使用self.clients.claim()sw2.js。激活sw2.js后,sw1.js将被标记为多余。

另一种询问我认为同样问题的方法是,您是否可以让多个服务工作者同时控制同一个客户端页面。答案是否定的,您最多可以拥有一个控制任何客户端页面的服务工作者,并且只有该服务工作人员才能响应源自该页面的fetch个事件。

使用importScripts共享公共处理程序

使用importScripts()来提取在不同JavaScript文件中定义的逻辑听起来像是一种合理的方法,而不是尝试注册具有相同范围的多个服务工作者。以这种方式使用importScripts()时需要注意以下几点:

  • importScripts()需要在服务工作者代码的初始启动执行期间调用,而不是在事件处理程序内部。即不支持importScripts()的“延迟加载”。
  • importScripts()按照列出的顺序逐个同步地执行文件内的所有代码。您可以在自己导入的文件中包含多个importScripts()importScripts(),并且它们都将按照定义的顺序执行。
  • 在导入的脚本中,如果代码位于顶级服务工作者中,self将设置为相同的ServiceWorkerGlobalScope。即,在导入的脚本内部或在顶级服务工作者内部调用self.addEventListener()之间没有区别。
  • (这与你的问题没有直接关系,但是很高兴知道:)默认情况下会缓存通过importScripts()引用的文件,使用内置于浏览器中的相同机制来缓存顶部级别的服务工作者文件。虽然正在进行一些更改服务工作者规范以进行更改,但截至目前,只要文件名不变,这些缓存的importScripts()文件将无限期使用。因此,最佳做法是在importScripts()引用的任何内容的文件名中包含版本号或散列。

多次获取事件处理程序

当您多次拨打self.addEventListener('fetch')时会发生什么?

从上一节我们知道,这些多个调用是否来自importScripts()资源或顶级服务工作者,这无关紧要。它们都在相同的全球范围内运作。

行为是明确定义的:当客户端页面发出请求时,它将逐个触发控制服务工作者的fetch处理程序,按照它们的注册顺序,直到第一次调用event.respondWith()。一个fetch事件处理程序调用{​​{1}},不会触发其他获取事件处理程序,并且该处理程序的唯一责任是(最终)将respondWith()返回到客户端页面。 / p>

由于Response来电的顺序很重要,请确保以适当的顺序列出self.addEventlistener('fetch')中的文件,并在之前或之后包含您对importScripts()的通话您可以在顶级服务工作者中定义任何importScripts()事件处理程序,具体取决于您希望优先使用哪个。

虽然您可以使用条件逻辑来确定是否调用fetch,但该逻辑不能是异步的,因为服务工作者不会等待查看是否调用event.respondWith()。它需要同步移动到下一个event.respondWith()处理程序(假设有一个)。

因此,在event处理程序中,您可以使用像

这样的条件逻辑
fetch

但你不能使用条件逻辑,如:

// This can be executed synchronously.
if (event.request.url.endsWith('.html')) {
  event.respondWith(...);
}

如果您想亲自查看多处理程序行为,可以探索live code sample