Skip to content

Instantly share code, notes, and snippets.

@robbiejaeger
Last active February 2, 2021 23:55
Show Gist options
  • Save robbiejaeger/a7c9db22c15815dcfc641e6ad7dcbfbb to your computer and use it in GitHub Desktop.
Save robbiejaeger/a7c9db22c15815dcfc641e6ad7dcbfbb to your computer and use it in GitHub Desktop.
  • Show 'SyncManager' and 'Notification' objects in window
  • Request approval for notifications in the browser
  • If serviceWorker registration and installation is successful and the serviceWorker is ready, then add an event listener to the submit button to add an article to the sync queue

main.js

if ('serviceWorker' in navigator && 'SyncManager' in window && 'Notification' in window) {
  window.addEventListener('load', () => {
    fetchLatestHeadlines();
    navigator.serviceWorker.register('./service-worker.js')
      .then(registration => navigator.serviceWorker.ready)
      .then(registration => {
        Notification.requestPermission();
        $('#submit-article').on('click', function(event) {
          let headline = $('#headline-input').val();
          let byline = $('#byline-input').val();

          navigator.serviceWorker.controller.postMessage({ 
            type: 'add-article',
            article: { headline, byline, id: Math.random() }
          });
        });

      }).catch(err => {
        // registration failed :(
        console.log(`ServiceWorker registration failed: ${err}`);
      });
  });
}

  • Add service worker event listener for a message of type add-article
  • Add synceQueue to store data about the article that was previously retrieved from the form
  • Register an addArticle sync event

service-worker.js

self.addEventListener('message', (event) => {
  if (event.data.type === 'add-article') {
    syncQueue.push(event.data.article);
  }
  self.registration.sync.register('addArticle')
});

let syncQueue = [];

  • Add handler for any sync event, and then look for a sync event with a tag of addArticle
  • Wait untill will try to run addArticle immediately, but if it fails, then it will try again at some time, then next time we know it will try is a network event
  • Once we get a success, send a message to our client-side code that the service worker client has new information
  • Give the user a notification that the article has been sent

service-worker.js

self.addEventListener('sync', function (event) {
  if (event.tag === 'addArticle') {
    event.waitUntil(addArticle()
      .then(response => response.json())
      .then(articles => {
        self.clients.matchAll().then(clients => {
          clients[0].postMessage({ articles: articles });
        });
        self.registration.showNotification("Added new article");
      })
      .catch(error => {
        console.log('error: ', error);
      })
    );
  }
});

  • Add the addArticle function (we're just returning the promise and resolving it in the previous event listner)

service-worker.js

const addArticle = () => {
  let newestArticle = syncQueue.shift();
  return fetch('/api/v1/articles', {
    method: 'POST',
    body: JSON.stringify(newestArticle),
    headers: { 'Content-Type': 'application/json' }
  });
}

  • Add event listener for service worker message

main.js

navigator.serviceWorker.addEventListener('message', function(event) {
  if (event.data.articles) {
    appendArticles(event.data.articles);
  }
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment