渐进式Web应用程序 Uncaught (in promise) TypeError: Failed to fetch。

29

我开始学习PWA(渐进式Web应用程序),但我遇到了问题,控制台会“抛出”错误,提示“未捕获的(在Promise中)TypeError:获取失败。”

有人知道可能是什么原因吗?

let CACHE = 'cache';

self.addEventListener('install', function(evt) {
    console.log('The service worker is being installed.');
    evt.waitUntil(precache());
});

self.addEventListener('fetch', function(evt) {
    console.log('The service worker is serving the asset.');
    evt.respondWith(fromCache(evt.request));
});
function precache() {
    return caches.open(CACHE).then(function (cache) {
        return cache.addAll([
            '/media/wysiwyg/homepage/desktop.jpg',
            '/media/wysiwyg/homepage/bottom2_desktop.jpg'
        ]);
    });
}
function fromCache(request) {
    return caches.open(CACHE).then(function (cache) {
        return cache.match(request).then(function (matching) {
            return matching || Promise.reject('no-match');
        });
    });
}
6个回答

27

我认为这是因为你没有备用策略。 event.respondWith 带有一个承诺,如果出现错误,你必须捕获它。

因此,我建议你将代码从以下代码更改:

self.addEventListener('fetch', function(evt) {        
    console.log('The service worker is serving the asset.');
    evt.respondWith(fromCache(evt.request));
});                   

翻译成像这样:

addEventListener('fetch', function(event) {
  event.respondWith(
    caches.match(event.request)
      .then(function(response) {
        if (response) {
          return response;     // if valid response is found in cache return it
        } else {
          return fetch(event.request)     //fetch from internet
            .then(function(res) {
              return caches.open(CACHE_DYNAMIC_NAME)
                .then(function(cache) {
                  cache.put(event.request.url, res.clone());    //save the response for future
                  return res;   // return the fetched data
                })
            })
            .catch(function(err) {       // fallback mechanism
              return caches.open(CACHE_CONTAINING_ERROR_MESSAGES)
                .then(function(cache) {
                  return cache.match('/offline.html');
                });
            });
        }
      })
  );
});          

注意: 缓存有许多策略,这里展示的是 离线优先 的方法。了解更多信息,请阅读必读文献。


1
截至2021年4月,Chrome最近宣布这种回退将很快成为PWA可安装性的必要条件。尽管他们后来放松了立场,但如果没有实施回退,Chrome仍会发出各种警告和获取失败。 - defraggled

21

我找到了解决相同错误的方法,我的情况是当服务工作者找不到一个文件*时显示这个错误。通过在Chrome会话的开发工具中跟踪网络,并确定服务工作者未能找到的不存在的文件并删除要注册的文件数组来修复它。

  '/processos/themes/base/js/processos/step/Validation.min.js',
  '/processos/themes/base/js/processos/Acoes.min.js',
  '/processos/themes/base/js/processos/Processos.min.js',
  '/processos/themes/base/js/processos/jBPM.min.js',
  '/processos/themes/base/js/highcharts/highcharts-options-white.js',
  '/processos/themes/base/js/publico/ProcessoJsController.js',
 // '/processos/gzip_457955466/bundles/plugins.jawrjs',
 // '/processos/gzip_N1378055855/bundles/publico.jawrjs',
 // '/processos/gzip_457955466/bundles/plugins.jawrjs',
  '/mobile/js/about.js',
  '/mobile/js/access.js',

*我为自己加粗了解决方案... 我从一个缓存文件开始,然后添加另一个... 直到我得到一个错误路径,还要定义作用域 {scope: '/'} 或 {scope: './'} - 由lawrghita编辑


2
哇,我为这个问题工作了好几天!原来只是 ".jpg" 改成 ".png" 就可以了。唉,感谢! - Seth B

14

我也遇到了同样的错误。在我的情况下,Adblock 拦截了一个以 "ad" 开头的 URL(例如 /adsomething.php)的获取。


3
刚刚遇到了同样的问题。我使用了gitea,并且有一个以“Ad”开头的仓库。几乎所有的页面都出现了异常,解除在我的gitea网站上的广告拦截程序后问题得到了解决! - Roemer
这解决了我2小时的问题。非常感谢。 - Luca Iaconelli
我也遇到了这个问题。我正在使用Workbox。有没有什么解决方法,不需要更改目录或强制终端用户关闭广告拦截器? - Adam Youngers

3
在我的情况下,需要缓存的文件没有被找到(请检查网络控制台),这可能与相对路径有关,因为我正在使用localhost,并且该站点位于子目录内,因为我正在XAMPP服务器上开发多个项目。
因此,我进行了如下更改:
let cache_name = 'Custom_name_cache';

let cached_assets = [
    '/',
    'index.php',
    'css/main.css',
    'js/main.js'
];

self.addEventListener('install', function (e) {
    e.waitUntil(
        caches.open(cache_name).then(function (cache) {
            return cache.addAll(cached_assets);
        })
    );
});

请注意下面的内容:在cached_assets上,要加上 "./"。
let cache_name = 'Custom_name_cache';

let cached_assets = [
    './',
    './index.php',
    './css/main.css',
    './js/main.js'
];

self.addEventListener('install', function (e) {
    e.waitUntil(
        caches.open(cache_name).then(function (cache) {
            return cache.addAll(cached_assets);
        })
    );
});

0

在添加或获取任何路径(如/offline.html/main.js)之前,请尝试使用/


0

缓存文件的引用应该是正确的,否则获取操作将失败。即使只有一个引用不正确,整个获取操作也会失败。

let cache_name = 'Custom_name_cache';


let cached_files = [
    '/',
    'index.html',
    'css/main.css',
    'js/main.js'
]; 
// The reference here should be correct. 

self.addEventListener('install', function (e) {
    e.waitUntil(
        caches.open(cache_name).then(function (cache) {
            return cache.addAll(cached_files);
        })
    );
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接