关注This Discussion,哪里有评论说明
通过重写self.fetch,self.XMLHttpRequest和self.caches(for cache.add /中的addAll)?看起来这些可以让你拦截网络请求并在主SW脚本看到之前操纵响应。
我一直在寻找任何有关此类内容的文档,而且似乎找不到任何文档。
在我只是需要 multiple
服务工作者共存于一个范围的情况下,
在其中一个中有importScripts
后导入另一个的事件处理程序,
我如何修补fetch /避免获取竞争/让两个获取处理程序都工作?
答案 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。