Angular7:服务人员无法正常工作

时间:2019-01-03 05:03:23

标签: javascript angular service-worker angular7 angular-service-worker

我有一个专职服务人员,并且已缓存声音(mp3文件),以便可以离线播放它们。这是ngsw-config-json

{
  "index": "/index.html",
  "assetGroups": [{
    "name": "app",
    "installMode": "prefetch",
    "resources": {
      "files": [
        "/favicon.ico",
        "/index.html",
        "/*.css",
        "/*.js",
        "/*.svg",
        "/*.eot",
        "/*.woff",
        "/*.woff2",
        "/*.tff"
      ]
    }
  }, {
    "name": "assets",
    "installMode": "prefetch",
    "updateMode": "prefetch",
    "resources": {
      "files": [
        "/assets/sounds/character1/**",
        "/assets/sounds/character2/**"
      ]
    }
  }]
}

在我的网络应用中,声音的播放方式如下:

let audioLink = `/assets/sounds/${character}/${soundURL}`;
let player = new Audio(audioLink);
player.play()

该网站离线运行。 HTML,CSS,JS,JSON文件均已缓存。但是声音没有播放(当我尝试播放时,出现上面显示的错误)。

在Chrome开发者工具> 应用程序> 缓存中,我可以看到一些声音(路径),但不是全部。但是其中没有都可以脱机工作。

有时会出现这些错误:

  • GET "path/to/file" net::ERR_ABORTED 504 (Gateway Timeout)
  • Uncaught (in promise) DOMException
  • Failed to load resource: net::ERR_INTERNET_DISCONNECTED

有时它还表示manifest.json存在问题,但是没有问题,因为它在线时显示在开发人员工具的清单部分中。

此问题是否有解决方法?这不是Chrome的错误,因为我在Safari和Firefox中也看到了相同的行为。我知道新的chrome版本中有一个错误,由于这个错误,favicon.ico不会脱机显示

不确定是否有帮助,但是here是指向托管Web应用程序的链接。如果您在Chrome开发者工具中看到“网络”标签,则可以看到mp3文件正在“下载”,但它们不能离线播放。

生成用于生产(ng build --prod --base-href="/"的网站后,我调查了ngsw.json,这就是我所看到的(删除了一些行):

{
  "name": "assets",
  "installMode": "prefetch",
  "updateMode": "prefetch",
  "urls": [
    "/assets/sounds/character1/sound one.mp3",
    "/assets/sounds/character1/sound two.mp3",
    "/assets/sounds/character2/sound three.mp3"
    "/assets/sounds/character2/sound four.mp3"
  ],
  "patterns": []
}

Here是完整生成的ngsw.json。一切都已设置为预缓存,而不是延迟缓存。

所有这些资产URL也在"hashTable"对象中。我还看到它们是在chrome开发人员工具(开发人员工具>网络)中下载的,但我只在应用程序缓存部分中看到了其中的某些部分(也许是总共150中的前20-30)。

我在这里做错了什么?这可能是Angular 7错误吗?我也看到过其他关于类似问题的其他StackOverflow和Reddit问题。

我尝试过的事情正在改变

let audioLink = `/assets/sounds/${character}/${soundURL}`;

let audioLink = `assets/sounds/${character}/${soundURL}`;

(开始时删除了斜杠),但这没有什么不同。

我完全确定所有声音文件路径都是正确的,因为当网站在线运行时绝对没有错误。

除上述内容外,我尝试手动更改所有URL,并在应该有空格的地方插入%20。例如,将"/assets/sounds/character1/sound one.mp3"更改为"/assets/sounds/character1/sound%20one.mp3",但这也不起作用。

我注意到的一件事是,如果您是第一次访问该网站,并等待所有声音下载,然后不重要,然后关闭Internet连接并尝试该站点,则所有声音都会起作用。但是只有一段时间(通常在10-15分钟左右),它们才会停止工作。我已经在Chrome,Chrome Android,Firefox,Safari和IOS Safari上进行了测试。

编辑:根据某人的建议,我尝试更改

{
  "name": "assets",
  "installMode": "prefetch",
  "updateMode": "prefetch",
  "urls": [
    "/assets/sounds/character1/sound one.mp3",
    "/assets/sounds/character1/sound two.mp3",
    "/assets/sounds/character2/sound three.mp3"
    "/assets/sounds/character2/sound four.mp3"
  ],
  "patterns": []
}

{
  "name": "assets",
  "installMode": "prefetch",
  "updateMode": "prefetch",
  "urls": [
    "/assets/sounds/**"
  ],
  "patterns": []
}

,但是仍然存在相同的问题:声音被离线缓存大约10至15分钟,之后它们便无法离线播放。我只能在Chrome和Chrome Android中对此进行测试。

2 个答案:

答案 0 :(得分:3)

我尝试制作一个演示来隔离错误,并且似乎可以正常工作。在应用程序缓存中发现了一些奇怪的网址:Imgur

不确定是引起问题的原因。您已经提到,使设备脱机后声音会起作用,我想这是浏览器缓存而不是脱机缓存。 当我尝试刷新页面时,声音永远无法正常工作。我的猜测是ngsw的配置或ngsw缓存文件的方式与Audio类不兼容。

您可以通过先使用@angular/common/http来将blob传递到Audio中来测试它是否有效。我在想这是因为音频文件似乎位于不同的缓存目录中(请参见屏幕截图)。出于某些原因,css / js文件的存储方式似乎有所不同,音频文件只能(离线)访问角度文件。

发布评论的时间太长

答案 1 :(得分:2)

我在@codeninja的帮助下找到了问题的答案。

首先,audioLink必须是声音的直接链接。我将网站托管在Github上,因此链接看起来像这样:

let url = `sounds/path_to_sound.mp3`
let audioLink = `https://raw.githubusercontent.com/username/repo_name/master/assets/sounds/${url}`;

第二,我们不能仅将sound.play()Audio()方法一起使用,我们必须使用HttpClient来检索音频。我不确定为什么会这样,但是codeninja建议ngsw缓存文件的方式与Audio类不兼容。我不确定这是否成立,但是我发现离线时必须使用HttpClient来检索音频Blob(如下所示)。如果不是,则会出现response not Ok错误。即使我给了直接链接https://raw.githubusercontent.com/username/repo_name/master/assets/sounds/direct.mp3,它也会抛出相同的错误。

总而言之,代码看起来像这样:

首先有一个getSound()函数:

getSound(url) {
  return this.http.get(url, {responseType: 'blob'});
}

然后在另一个函数(playSound(url))中,我们有这个功能:

playSound(url) {
  let audioLink = `https://raw.githubusercontent.com/username/repo_name/master/assets/sounds/${url}`;

  this.getSound(audioLink)
    .subscribe(data => {
      console.log(data);
      // data is an audio blob
      let url = URL.createObjectURL(data);

      let sound = document.createElement('audio');
      sound.src = url;
      sound.play();
    })
}

此外,我还必须更改我的ngsw-config.json。我只更改了“资产”部分,因此我将向您展示:

{
  "name": "assets",
  "installMode": "lazy",
  "updateMode": "prefetch",
  "resources": {
    "files": [
    ],
    "urls": [
       "https://raw.githubusercontent.com/username/repo_name/master/assets/sounds/**"
    ]
  }
}

我也无法使其与“预取”一起使用。尽管现在缓存的声音可以脱机播放,但它们只会在以前播放过的情况下播放,因为它设置为“惰性”。

我在Chrome,Chrome Android和Firefox上测试了该解决方案,并且运行良好。