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 从未准备好的主要内容,如果未能解决你的问题,请参考以下文章

如何每10秒发送一次通知?

`self.Clients.claim()` 有啥用

如何在 Ruby on Rails 中注册服务工作者?

在 https iframe 中注册服务人员时出现 DOMException

无法获取 serviceWorkerRegistration

Web 推送通知在 Android 上工作,但在 IOS 上不工作