navigator.serviceWorker 从未准备好
Posted
技术标签:
【中文标题】navigator.serviceWorker 从未准备好【英文标题】:navigator.serviceWorker is never ready 【发布时间】:2015-04-26 05:18:25 【问题描述】:我成功注册了一个service worker,但是随后代码
navigator.serviceWorker.ready.then(function(serviceWorkerRegistration)
// Do we already have a push message subscription?
....
hangs -- 该函数永远不会被调用。为什么?
【问题讨论】:
【参考方案1】:问题在于 service-worker.js 文件存储在 assets
子目录中。
不要这样做:将 service-worker.js 存储在 root of your app
(或更高版本)中。这样您的应用就可以访问 service-worker。
见html5Rocks article--
register 方法的一个微妙之处是 service worker 文件的位置。在这种情况下,您会注意到 service worker 文件位于域的根目录。这意味着服务工作者的范围将是整个源。换句话说,这个 service worker 将接收这个域上所有东西的 fetch 事件。如果我们在 /example/sw.js 中注册 service worker 文件,那么 service worker 只会看到 URL 以 /example/ 开头的页面(即 /example/page1/、/example/page2/)的 fetch 事件。
已添加
一个新问题是,如果页面被硬重新加载,serviceworker 永远不会准备好。随后的软页面重新加载工作正常。谷歌自己的示例代码失败。 See the Chrome bug report.
错误修复已包含在 Chrome 44 中。
【讨论】:
我也面临同样的问题。我的服务工作者在test.example.com/background-worker.js 注册,我的javascript 代码 navigator.serviceWorker.ready.then(function(serviceWorkerRegistration) 正在test.example.com/blog 上运行它正在成功注册,但从未调用此函数。知道可能是什么问题? 查看答案中新增的信息 我头疼了好几个小时,直到我看到这个:D 对我来说这太糟糕了:不得不关闭浏览器的选项卡 (Chrome
) 并再次打开它。清除缓存存储、浏览器缓存和注销 Service Worker 均无效。
非常感谢。这两天我一直在拐弯抹角,我所要做的就是将 sw.js 从脚本移到根目录...【参考方案2】:
正如在接受的答案中所说,问题确实可能是因为您的服务工作者 JS 文件与当前页面位于不同的路径中。
默认情况下,Service Worker 的作用域是其 JS 文件的路径。如果您的 JS 文件可以通过 http://www.example.com/assets/js/service-worker.js
访问,那么您的 service worker 将只为以 /assets/js/
开头的 URL 工作/“准备好”。
但是,您可以更改 Service Worker 的范围。首先,如果使用scope
选项,则需要注册:
navigator.serviceWorker.register('http://www.example.com/assets/js/service-worker.js',
scope: '/',
);
如果你这样做了,你会在 Chrome 控制台中得到错误:
提供的范围('/')的路径不在最大范围内 允许('/assets/js/')。调整范围,移动Service Worker 脚本,或使用 Service-Worker-Allowed HTTP 标头来允许 范围。
/admin/#/builder:1 Uncaught (in promise) DOMException: Failed to 为范围 ('http://www.example.com/') 注册一个 ServiceWorker 脚本
('http://www.example.com/assets/js/service-worker.js'): 的路径 提供的范围 ('/') 不在允许的最大范围内 ('/assets/js/')。调整范围,移动 Service Worker 脚本,或 使用 Service-Worker-Allowed HTTP 标头来允许范围。
然后您需要在您网站的根目录创建一个.htacess
文件,其中包含以下内容:
<IfModule mod_headers.c>
<Files ~ "service-worker\.js">
Header set Service-Worker-Allowed: /
</Files>
</IfModule>
【讨论】:
【参考方案3】:遇到了同样的问题,但是将 service worker 和安装脚本放在同一个目录中并没有解决这个问题。对我来说,解决方案是在 url 的末尾添加一个“/”。 所以我有:
http://localhost:9105/controller/main.js
- 安装脚本
http://localhost:9105/controller/sw.js
- 服务人员
http://localhost:9105/controller/index.html
- 页面
当浏览器中的 url 为 http://localhost:9105/controller
时,service worker 从未准备好,但当 url 为 http://localhost:9105/controller/
时,它工作正常。
我用下面的代码来控制这个
if (!window.location.href.endsWith('/'))
window.location.assign(window.location.href + '/')
【讨论】:
【参考方案4】:在我的情况下 - 只需关闭选项卡并再次打开它...
【讨论】:
所以它不是第一次适用于所有用户,这不是一个解决方案;)【参考方案5】:将 service-worker.js 文件添加到您的项目根目录
您可以从Link下载service-worker.js文件
并使用以下代码注册服务工作者。
if ('serviceWorker' in navigator)
navigator.serviceWorker
.register('./service-worker.js', scope: './' )
.then(function (registration)
console.log("Service Worker Registered");
)
.catch(function (err)
console.log("Service Worker Failed to Register", err);
)
【讨论】:
以上是关于navigator.serviceWorker 从未准备好的主要内容,如果未能解决你的问题,请参考以下文章
在 https iframe 中注册服务人员时出现 DOMException