Hank Phung
Hank Phung

Reputation: 2149

Progressive Web App: How to detect and handle when connection is up again

With a PWA, we can handle when the device connection is down with offline mode. But how do we detect a fixed network connection and automatically reload/re-activate the application?

Upvotes: 32

Views: 33202

Answers (4)

tony19
tony19

Reputation: 138526

You could monitor the offline and online events, which are widely supported. Further, you could test connectivity by attempting to fetch HEAD from the target server URL:

// Test this by running the code snippet below and then
// use the "Offline" checkbox in DevTools Network panel

window.addEventListener('online', handleConnection);
window.addEventListener('offline', handleConnection);

function handleConnection() {
  if (navigator.onLine) {
    isReachable(getServerUrl()).then(function(online) {
      if (online) {
        // handle online status
        console.log('online');
      } else {
        console.log('no connectivity');
      }
    });
  } else {
    // handle offline status
    console.log('offline');
  }
}

function isReachable(url) {
  /**
   * Note: fetch() still "succeeds" for 404s on subdirectories,
   * which is ok when only testing for domain reachability.
   *
   * Example:
   *   https://google.com/noexist does not throw
   *   https://noexist.com/noexist does throw
   */
  return fetch(url, { method: 'HEAD', mode: 'no-cors' })
    .then(function(resp) {
      return resp && (resp.ok || resp.type === 'opaque');
    })
    .catch(function(err) {
      console.warn('[conn test failure]:', err);
    });
}

function getServerUrl() {
  return document.getElementById('serverUrl').value || window.location.origin;
}
<fieldset>
  <label>
    <span>Server URL for connectivity test:</span>
    <input id="serverUrl" style="width: 100%">
  </label>
</fieldset>
<script>document.getElementById('serverUrl').value = window.location.origin;</script>

<p>
  <i>Use Network Panel in DevTools to toggle Offline status</i>
</p>

One technique of handling this:

  • Offline event

    • show offline icon/status
    • enable only features that are available offline (via cached data)
  • Online event

    • show online icon/status
    • enable all features

Upvotes: 68

LeonH
LeonH

Reputation: 1037

A common practice in PWAs is to follow the Application Shell approach to your application. This would allow you to cache the Application Shell upon entry, and then load the data based upon the connection.

The most common method for caching and serving in this approach is to serve from cache with fallback to network, where whenever the resource requested is not available in the cache then you send the request via the network and cache the response. Then serve from the cache.

This allows for a more graceful degradation when you are on a spotty connection, such as on the train.

An example of implementing this:

const cacheName = "my-cache-v1"

self.addEventListener('fetch', (event) => {
  if (event.request.method === 'GET') {
    event.respondWith(
      caches.match(event.request).then((response) => {
        if (response) {
          return response;
        }
        return fetch(event.request).then((response) => {
          return caches.open(cacheName).then((cache) => {
            cache.put(event.request.url, response.clone());
            return response;
          });
        });
      })
    );
  }
});

In the above example (only one of the required steps in a Service Worker life cycle), you would also need to delete outdated cache entries.

Upvotes: 3

Nicolas Hoizey
Nicolas Hoizey

Reputation: 2031

Be careful with the online event, that only tells the device if connected. It can be connected to a WiFi hotspot without actual Internet connectivity (because of credentials for example).

Upvotes: 30

layonez
layonez

Reputation: 1785

Most of the services I've seen use the following practice: with an increasing to a certain value timeout, trying to contact the server. When the maximum timeout value is reached, an indicator with a manual recconect button appears which indicates in how many time the next attempt of reconnect will occur

Upvotes: 2

Related Questions