简体   繁体   English

如何在Firefox Service Worker中处理206个响应

[英]How to handle 206 responses in Firefox service workers

While testing service workers for a project and using this example from google: 在测试服务人员的项目并使用Google提供的示例时:

/*
 Copyright 2016 Google Inc. All Rights Reserved.
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at
     http://www.apache.org/licenses/LICENSE-2.0
 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
*/

// Names of the two caches used in this version of the service worker.
// Change to v2, etc. when you update any of the local resources, which will
// in turn trigger the install event again.
const PRECACHE = 'precache-v1';
const RUNTIME = 'runtime';

// A list of local resources we always want to be cached.
const PRECACHE_URLS = [
  'index.html',
  './', // Alias for index.html
  'styles.css',
  '../../styles/main.css',
  'demo.js'
];

// The install handler takes care of precaching the resources we always need.
self.addEventListener('install', event => {
  event.waitUntil(
    caches.open(PRECACHE)
      .then(cache => cache.addAll(PRECACHE_URLS))
      .then(self.skipWaiting())
  );
});

// The activate handler takes care of cleaning up old caches.
self.addEventListener('activate', event => {
  const currentCaches = [PRECACHE, RUNTIME];
  event.waitUntil(
    caches.keys().then(cacheNames => {
      return cacheNames.filter(cacheName => !currentCaches.includes(cacheName));
    }).then(cachesToDelete => {
      return Promise.all(cachesToDelete.map(cacheToDelete => {
        return caches.delete(cacheToDelete);
      }));
    }).then(() => self.clients.claim())
  );
});

// The fetch handler serves responses for same-origin resources from a cache.
// If no response is found, it populates the runtime cache with the response
// from the network before returning it to the page.
self.addEventListener('fetch', event => {
  // Skip cross-origin requests, like those for Google Analytics.
  if (event.request.url.startsWith(self.location.origin)) {
    event.respondWith(
      caches.match(event.request).then(cachedResponse => {
        if (cachedResponse) {
          return cachedResponse;
        }

        return caches.open(RUNTIME).then(cache => {
          return fetch(event.request).then(response => {
            // Put a copy of the response in the runtime cache.
            return cache.put(event.request, response.clone()).then(() => {
              return response;
            });
          });
        });
      })
    );
  }
});

source: https://github.com/GoogleChrome/samples/blob/gh-pages/service-worker/basic/service-worker.js 来源: https : //github.com/GoogleChrome/samples/blob/gh-pages/service-worker/basic/service-worker.js

I discovered that Firefox (in contrast to safari and chrome) throws errors within event.waitUntil() as well as event.respondWith() if something does not work with the fetch requests (even if its just a 206 partial content response): 我发现Firefox(与野生动物园和Chrome浏览器相反)会在event.waitUntil()以及event.respondWith()内引发错误,如果某些操作不适用于提取请求(即使它只是206部分内容响应):

Service worker event waitUntil() was passed a promise that rejected with 'TypeError: Cache got basic response with bad status 206 while trying to add request 服务工作者事件waitUntil()被传递了一个承诺,该承诺被'TypeError拒绝:尝试添加请求时,高速缓存获得状态为206的基本响应

That behaviour breaks the installer. 这种行为会破坏安装程序。 If I add a .catch() to the installer like this 如果我这样向安装程序添加.catch()

self.addEventListener('install', event => {
  event.waitUntil(
    caches.open(PRECACHE)
      .then(cache => cache.addAll(PRECACHE_URLS))
      .then(self.skipWaiting())
      .catch(function(err){
        console.log(err);
        self.skipWaiting();
      })
  );

}); });

I presume the first 206 will make the precache stop (?) 我认为前206个将使预缓存停止(?)

Also after that the sw gets installed but once in a while I get a 另外在安装了sw之后,偶尔我会得到一个

Service worker event respondWith() was passed a promise that rejected with 'TypeError: Cache got basic response with bad status 206 while trying to add request 服务工作者事件responseWith()已传递一个承诺,该承诺被'TypeError:尝试添加请求时,缓存状态为206的基本响应返回错误状态

and even if that does not happen, if I try to open the a link to the url that threw the 206 error while installation/precaching I get: 即使没有发生,如果我尝试在安装/预缓存时尝试打开指向引发206错误的网址的链接,则会得到:

Failed to load ' https://xxxx/yyyyy.mp3 '. 无法加载“ https://xxxx/yyyyy.mp3 ”。 A ServiceWorker passed a promise to FetchEvent.respondWith() that rejected with 'TypeError: Cache got basic response with bad status 206 while trying to add request https://xxxx/yyyyy.mp3 '. 一个ServiceWorker向FetchEvent.respondWith()传递了一个承诺,该承诺以“ TypeError:Cache尝试添加请求https://xxxx/yyyyy.mp3 ”时得到了状态为206的基本响应。

在浏览器内部,错误看起来像文件已损坏

how can I handle this kind of error properly? 如何正确处理此类错误? catching like above doesn't make much sense for it breaks the forced precaching. 像上面那样捕获并没有多大意义,因为它破坏了强制预缓存。 And even if that would be acceptable, it seems to interfere with every request happening from then on and might cause trouble later on. 即使那是可以接受的,它似乎也会干扰从那时起发生的每个请求,并可能在以后引起麻烦。

one half of the problem i could solve by moving the return statement from within the cache.put() function outside of it: 我可以通过将return语句从cache.put()函数内部移出来解决一半的问题:

self.addEventListener('fetch', event => {
  // Skip cross-origin requests, like those for Google Analytics.
  if (event.request.url.startsWith(self.location.origin)) {
    event.respondWith(
      caches.match(event.request).then(cachedResponse => {
        if (cachedResponse) {
          return cachedResponse;
        }

        return caches.open(RUNTIME).then(cache => {
          return fetch(event.request).then(response => {
            // Put a copy of the response in the runtime cache.
            cache.put(event.request, response.clone()).then(() => {
              console.log("logged a file into RUNTIME:");
              console.log(response);
            });
            return response; // and return anyhow whatever came back
          });
        });
      })
    );
  }
});

this way the sw does not wait for the cache.put() to be successful and yet it gets cached most of the times. 这样,sw不会等待cache.put()成功,但是大多数时候它都会被缓存。

this solves the most urgent issue but problems still are 这解决了最紧迫的问题,但问题仍然存在

a) forced precaching still gets cancelled by 206 responses b) in case I would want to make sure that requests are cached in runtime, i would still need to make some retry() function or sth. a)强制预缓存仍然被206个响应取消b)万一我想确保请求在运行时被缓存,我仍然需要做一些retry()函数或其他操作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM