离线时在 Progressive Web App 中处理获取请求

Posted

技术标签:

【中文标题】离线时在 Progressive Web App 中处理获取请求【英文标题】:Handling fetch requests in Progressive Web App when offline 【发布时间】:2017-06-28 04:32:39 【问题描述】:

我一直在关注渐进式 Web 应用程序上的 this tutorial,我正在尝试找到一种在应用程序离线时向用户呈现某种消息的方法。到目前为止,我的代码与教程几乎相同:

var cacheName = 'demoPWA-v1'; var filesToCache = [ '/', '/index.html', '/js/app.js', '/icons/pwa-256x256.png' ]; self.addEventListener('install', function(e) console.log('[demoPWA - ServiceWorker] 安装事件已触发。'); e.等待直到( caches.open(cacheName).then(function(cache) console.log('[demoPWA - ServiceWorker] 缓存应用程序外壳...'); 返回 cache.addAll(filesToCache); ) ); ); self.addEventListener('activate', function(e) console.log('[demoPWA - ServiceWorker] 激活事件被触发。'); e.等待直到( caches.keys().then(function(keyList) 返回 Promise.all(keyList.map(function(key) 如果(键!==缓存名称) console.log('[demoPWA - ServiceWorker] 删除旧缓存...', key); 返回缓存。删除(键); )); ) ); 返回 self.clients.claim(); ); self.addEventListener('fetch', function(e) console.log('[demoPWA - ServiceWorker] Fetch 事件被触发。', e.request.url); e.respondWith( caches.match(e.request).then(function(response) 如果(响应) console.log('[demoPWA - ServiceWorker] 从缓存中检索...'); 返回响应; console.log('[demoPWA - ServiceWorker] 从 URL 检索...'); 返回获取(e.request); ) ); );

当我在 Chrome 中的 Application > Service Workers 下选中 Offline 复选框时,我收到了一些错误,如下所示:

我想知道是否有某种方法可以处理此错误,并在这样做的同时向用户显示某种消息,告知他们他们处于离线状态。

【问题讨论】:

获取,返回一个承诺。所以你可以抓住错误.. fetch(e.request).catch(function (e) (*do your stuff*) @Keith 您能否根据该逻辑发布答案?如果可以的话,也许可以更详细地解释一下。 可以,但是您会以什么方式通知用户?.. 最简单的就是使用警报,例如现在可以吗? @Keith 我想将消息写入一些 HTML 元素,但是为了展示解决方案,警报会做! 【参考方案1】:

以下是仅用于发出警报的模块,然后您可以将警报更改为使用 Jquery 或直接 DOM 来更新您的 HTML 页面..

self.addEventListener('fetch', function(e) 
    console.log('[demoPWA - ServiceWorker] Fetch event fired.', e.request.url);
    e.respondWith(
        caches.match(e.request).then(function(response) 
            if (response) 
                console.log('[demoPWA - ServiceWorker] Retrieving from cache...');
                return response;
            
            console.log('[demoPWA - ServiceWorker] Retrieving from URL...');
            return fetch(e.request).catch(function (e) 
               //you might want to do more error checking here too,
               //eg, check what e is returning..
               alert('You appear to be offline, please try again when back online');
            );
        )
    );
);

【讨论】:

事实证明,虽然这个想法很可靠,但我无法显示服务人员的警报。 (当你最初发布它时,我没有测试你的答案,因为我离开了我的电脑,并认为这样一个简单的解决方案肯定会起作用,但事实证明服务工作者有一些限制......) 我从来没有真正需要在 javascript 中使用 service workers,但是当我在 Win32 开发中使用 Thread 时,当你需要更新 GUI 时,你会向主线程发布消息。快速浏览在 Service Worker 中,您似乎也想在这里做同样的事情。 从服务人员向主线程发布消息。然后从那里处理警报/DOM 更新。【参考方案2】:

是的,你在做什么,这很有意义,只要你确定缓存不为空,因为你只是打算用它来显示离线警告。

MDN代码真的有问题catch()不工作,我做了一些修改,成功了,至于catch(),我还没来得及解决问题,如果你先找到解决方案,让我知道!代码如下:

var CACHE_VERSION = 1;

// Smallest identifier for a specific version of the cache
var CURRENT_CACHES = 
  font: 'OFFLINE_CACHE' + CACHE_VERSION
;

self.addEventListener('fetch', function(event) 
 // console.log(event);
// We only want to call event.respondWith() if this is a GET request for an HTML document.
  if (event.request.method === 'GET') 
    console.log('Handling fetch event for', event.request.url);

  event.respondWith(

    // Opens the cache object that starts with 'font'
    caches.open(CURRENT_CACHES['font']).then(function(cache) 
      return cache.match(event.request).then(function(response) 
        if (response) 
          console.log('Found cached answer:', response);
          return response;
         else 
        //Did not find answer in cache
        return fetch(event.request).then(function(fetchresponse) 
        console.log("Request Result - redirected:" + fetchresponse.redirected + ", status:" + fetchresponse.status + ", statusText:" + fetchresponse.statusText + ", type:" + fetchresponse.type + ", url:" + fetchresponse.url);
        if(fetchresponse.status == '200' || fetchresponse.status == '201' || fetchresponse.status == '202' || fetchresponse.status == '203' || fetchresponse.status == '204' || fetchresponse.status == '206')
               return fetchresponse;    
          else 
         console.log('The request returned http code 30*, 40* or 50*.');
         return false;
             
        ).catch(function(e) 
         //Offline version
        return new Response('<html><title></title><strong>Sorry, You are offline!</strong></html>', "status" : 202, "headers" : "Content-Type" : "text/html; charset=utf-8");
        );
        
      ).catch(function(error) 
        //This .catch () doesn't seem to work, as I said, but it won't give you any problems, it just takes up space.

        // Handles exceptions that come from match () or fetch ().

        console.error('  Error:', error);

        throw error;
      );
    )
  );
  ;
);

【讨论】:

以上是关于离线时在 Progressive Web App 中处理获取请求的主要内容,如果未能解决你的问题,请参考以下文章

离线时在设备上测试 iOS 应用

离线时在 iOS 上进行 http 调用

你的首个 Progressive Web App

Progressive Web App

Progressive Web App(PWA)介绍

PWA(Progressive Web App)入门系列:PWA简介