SlideShare a Scribd company logo
Web improvements @robertnyman
Promises
New improvements for web developers - frontend.fi, Helsinki
fulfilled = The action relating to the promise succeeded
rejected = The action relating to the promise failed
pending = Hasn't fulfilled or rejected yet
settled = Has fulfilled or rejected
var promise = new Promise(function(resolve, reject) {

// do a thing, possibly async, then…



if (/* everything turned out fine */) {

resolve("Stuff worked!");

}

else {

reject(Error("It broke"));

}

});
promise.then(function(result) {

console.log(result); // "Stuff worked!"

}, function(err) {

console.log(err); // Error: "It broke"

});
fetch()
XMLHttpRequest example
function reqListener() { 

var data = JSON.parse(this.responseText); 

console.log(data); 

}



function reqError(err) { 

console.log('Fetch Error :-S', err); 

}



var oReq = new XMLHttpRequest(); 

oReq.onload = reqListener; 

oReq.onerror = reqError; 

oReq.open('get', './api/some.json', true); 

oReq.send();
fetch() version
fetch('./api/some.json') 

.then( 

function(response) { 

if (response.status !== 200) { 

console.log('Looks like there was a problem. Status Code: ' + 

response.status); 

return; 

}



// Examine the text in the response 

response.json().then(function(data) { 

console.log(data); 

}); 

} 

) 

.catch(function(err) { 

console.log('Fetch Error :-S', err); 

});
Response metadata
fetch('users.json').then(function(response) { 

console.log(response.headers.get('Content-Type')); 

console.log(response.headers.get('Date'));



console.log(response.status); 

console.log(response.statusText); 

console.log(response.type); 

console.log(response.url); 

});
Response Types
basic
cors
opaque
Defining modes
same-origin
cors
cors-with-forced-preflight
no-cors
Defining modes
fetch('http://some-site.com/cors-enabled/some.json', {mode: 'cors'}) 

.then(function(response) { 

return response.text(); 

}) 

.then(function(text) { 

console.log('Request successful', text); 

}) 

.catch(function(error) { 

log('Request failed', error) 

});
Service Workers
It's a JavaScript Worker, so it can't access the DOM
directly. Instead responds to postMessages
Service worker is a programmable network proxy
It will be terminated when not in use, and restarted
when it's next needed
Makes extensive use of Promises
New improvements for web developers - frontend.fi, Helsinki
No Service Worker
HTTPS is Needed
Register and Installing a Service Worker
if ('serviceWorker' in navigator) {

navigator.serviceWorker.register('/sw.js').then(function(registration) {

// Registration was successful

console.log('ServiceWorker registration successful with scope: ',
registration.scope);

}).catch(function(err) {

// registration failed :(

console.log('ServiceWorker registration failed: ', err);

});

}
chrome://inspect/#service-workers
// The files we want to cache

var urlsToCache = [

'/',

'/styles/main.css',

'/script/main.js'

];



// Set the callback for the install step

self.addEventListener('install', function(event) {

// Perform install steps

});
Installing
Inside our install callback:
1. Open a cache
2. Cache our files
3. Confirm whether all the required
assets are cached or not
Install callback
var CACHE_NAME = 'my-site-cache-v1';

var urlsToCache = [

'/',

'/styles/main.css',

'/script/main.js'

];



self.addEventListener('install', function(event) {

// Perform install steps

event.waitUntil(

caches.open(CACHE_NAME)

.then(function(cache) {

console.log('Opened cache');

return cache.addAll(urlsToCache);

})

);

});
self.addEventListener('fetch', function(event) {

event.respondWith(

caches.match(event.request)

.then(function(response) {

// Cache hit - return response

if (response) {

return response;

}



return fetch(event.request);

}

)

);

});
Caching and Returning Requests
self.addEventListener('fetch', function(event) {

event.respondWith(

caches.match(event.request)

.then(function(response) {

// Cache hit - return response

if (response) {

return response;

}



// IMPORTANT: Clone the request. A request is a stream and

// can only be consumed once. Since we are consuming this

// once by cache and once by the browser for fetch, we need

// to clone the response

var fetchRequest = event.request.clone();



return fetch(fetchRequest).then(

function(response) {

// Check if we received a valid response

if(!response || response.status !== 200 || response.type !== 'basic') {

return response;

}



// IMPORTANT: Clone the response. A response is a stream

// and because we want the browser to consume the response

// as well as the cache consuming the response, we need

// to clone it so we have 2 stream.

var responseToCache = response.clone();



caches.open(CACHE_NAME)

.then(function(cache) {

cache.put(event.request, responseToCache);

});



return response;

}

);

})

);

});
Caching new requests cumulatively
Updating a Service Worker
1. Update your service worker JavaScript file.
2. Your new service worker will be started and the
install event will be fired.
3. New Service Worker will enter a "waiting" state
4. When open pages are closed, the old Service
Worker will be killed - new service worker will take
control.
5. Once new Service Worker takes control, its
activate event will be fired.
Updating a Service Worker
Cache management & whitelists
self.addEventListener('activate', function(event) {



var cacheWhitelist = ['pages-cache-v1', 'blog-posts-cache-v1'];



event.waitUntil(

caches.keys().then(function(cacheNames) {

return Promise.all(

cacheNames.map(function(cacheName) {

if (cacheWhitelist.indexOf(cacheName) === -1) {

return caches.delete(cacheName);

}

})

);

})

);

});
Push notifications
New improvements for web developers - frontend.fi, Helsinki
<button class="js-push-button" disabled> 

Enable Push Messages 

</button>
// Are Notifications supported in the service worker? 

if (!('showNotification' in ServiceWorkerRegistration.prototype)) { 

console.warn('Notifications aren't supported.'); 

return; 

}
// Check the current Notification permission. 

// If its denied, it's a permanent block until the 

// user changes the permission 

if (Notification.permission === 'denied') { 

console.warn('The user has blocked notifications.'); 

return; 

}
// Check if push messaging is supported 

if (!('PushManager' in window)) { 

console.warn('Push messaging isn't supported.'); 

return; 

}
// We need the service worker registration to check for a subscription 

navigator.serviceWorker.ready.then(function(serviceWorkerRegistration) { 

// Do we already have a push message subscription? 

serviceWorkerRegistration.pushManager.getSubscription() 

.then(function(subscription) { 

// Enable any UI which subscribes / unsubscribes from 

// push messages. 

var pushButton = document.querySelector('.js-push-button'); 

pushButton.disabled = false;



if (!subscription) { 

// We aren't subscribed to push, so set UI 

// to allow the user to enable push 

return; 

}



// Keep your server in sync with the latest subscriptionId

sendSubscriptionToServer(subscription);



// Set your UI to show they have subscribed for 

// push messages 

pushButton.textContent = 'Disable Push Messages'; 

isPushEnabled = true; 

}) 

.catch(function(err) { 

console.warn('Error during getSubscription()', err); 

}); 

});
{ 

"name": "Push Demo", 

"short_name": "Push Demo", 

"icons": [{ 

"src": "images/icon-192x192.png", 

"sizes": "192x192",

"type": "image/png" 

}], 

"start_url": "/index.html?homescreen=1", 

"display": "standalone", 

"gcm_sender_id": "123456789012", 

"gcm_user_visible_only": true 

}
<link rel="manifest" href="manifest.json">
Add to
Homescreen
Cache management & whitelistsApp Install Banners
App Install Banners prerequisites
You have a web app manifest file
You have a service worker registered on
your site. We recommend a simple custom
offline page service worker
Your site is served over HTTPS (you need a
service worker after all)
The user has visited your site twice over
two separate days during the course of two
weeks.
"You can do all of this?"
New improvements for web developers - frontend.fi, Helsinki
Robert Nyman
robertnyman.com

rnyman@google.com

Google
@robertnyman

More Related Content

What's hot (20)

PDF
React lecture
Christoffer Noring
 
PDF
Ember and containers
Matthew Beale
 
PDF
Introduction to React & Redux
Boris Dinkevich
 
PDF
Complex Architectures in Ember
Matthew Beale
 
PDF
Quick start with React | DreamLab Academy #2
DreamLab
 
PDF
React + Redux. Best practices
Clickky
 
PDF
Switch to React.js from AngularJS developer
Eugene Zharkov
 
PDF
ASP.NET MVC Internals
Vitaly Baum
 
PDF
Intro to Redux | DreamLab Academy #3
DreamLab
 
PDF
Reliable Javascript
Glenn Stovall
 
PDF
Redux Thunk - Fu - Fighting with Async
Artur Szott
 
DOCX
Converter suhu
Bayu Bakti
 
PDF
Angular server-side communication
Alexe Bogdan
 
PPTX
Redux training
dasersoft
 
PPTX
Getting started with ReactJS
Krishna Sunuwar
 
PDF
JavaScript Promises
Tomasz Bak
 
PDF
UI 모듈화로 워라밸 지키기
NAVER SHOPPING
 
PPTX
React и redux
Дмитрий Радыно
 
PDF
React state managmenet with Redux
Vedran Blaženka
 
PPTX
Service workers and the role they play in modern day web apps
Mukul Jain
 
React lecture
Christoffer Noring
 
Ember and containers
Matthew Beale
 
Introduction to React & Redux
Boris Dinkevich
 
Complex Architectures in Ember
Matthew Beale
 
Quick start with React | DreamLab Academy #2
DreamLab
 
React + Redux. Best practices
Clickky
 
Switch to React.js from AngularJS developer
Eugene Zharkov
 
ASP.NET MVC Internals
Vitaly Baum
 
Intro to Redux | DreamLab Academy #3
DreamLab
 
Reliable Javascript
Glenn Stovall
 
Redux Thunk - Fu - Fighting with Async
Artur Szott
 
Converter suhu
Bayu Bakti
 
Angular server-side communication
Alexe Bogdan
 
Redux training
dasersoft
 
Getting started with ReactJS
Krishna Sunuwar
 
JavaScript Promises
Tomasz Bak
 
UI 모듈화로 워라밸 지키기
NAVER SHOPPING
 
React state managmenet with Redux
Vedran Blaženka
 
Service workers and the role they play in modern day web apps
Mukul Jain
 

Similar to New improvements for web developers - frontend.fi, Helsinki (20)

PDF
Service workers
Pavel Zhytko
 
PDF
Service workers
jungkees
 
PDF
Service Worker - Reliability bits
jungkees
 
PPT
Service Workers for Performance
Patrick Meenan
 
PDF
PWA 與 Service Worker
Anna Su
 
PPTX
Introduction to Service Workers | Matteo Manchi
Codemotion
 
PDF
Rails for Mobile Devices @ Conferencia Rails 2011
Alberto Perdomo
 
PDF
Service workers
Eugene Lazutkin
 
PDF
Service worker API
Giorgio Natili
 
PDF
[1C1]Service Workers
NAVER D2
 
PDF
JQuery UK February 2015: Service Workers On Vacay
Natasha Rooney
 
PDF
JQuery UK Service Workers Talk
Natasha Rooney
 
PPTX
Building Progressive Web Apps for Windows devices
Windows Developer
 
PDF
Building Smart Async Functions For Mobile
Glan Thomas
 
PDF
Service workers are your best friends
Antonio Peric-Mazar
 
PDF
Sencha Roadshow 2017: Build Progressive Web Apps with Ext JS and Cmd
Sencha
 
PDF
A year with progressive web apps! #DevConMU
Antonio Peric-Mazar
 
ODP
Web program-peformance-optimization
xiaojueqq12345
 
PDF
Progressive Web Apps. What, why and how
Riza Fahmi
 
PDF
"Progressive Web Apps" by Riza Fahmi (Hacktiv8)
Tech in Asia ID
 
Service workers
Pavel Zhytko
 
Service workers
jungkees
 
Service Worker - Reliability bits
jungkees
 
Service Workers for Performance
Patrick Meenan
 
PWA 與 Service Worker
Anna Su
 
Introduction to Service Workers | Matteo Manchi
Codemotion
 
Rails for Mobile Devices @ Conferencia Rails 2011
Alberto Perdomo
 
Service workers
Eugene Lazutkin
 
Service worker API
Giorgio Natili
 
[1C1]Service Workers
NAVER D2
 
JQuery UK February 2015: Service Workers On Vacay
Natasha Rooney
 
JQuery UK Service Workers Talk
Natasha Rooney
 
Building Progressive Web Apps for Windows devices
Windows Developer
 
Building Smart Async Functions For Mobile
Glan Thomas
 
Service workers are your best friends
Antonio Peric-Mazar
 
Sencha Roadshow 2017: Build Progressive Web Apps with Ext JS and Cmd
Sencha
 
A year with progressive web apps! #DevConMU
Antonio Peric-Mazar
 
Web program-peformance-optimization
xiaojueqq12345
 
Progressive Web Apps. What, why and how
Riza Fahmi
 
"Progressive Web Apps" by Riza Fahmi (Hacktiv8)
Tech in Asia ID
 
Ad

More from Robert Nyman (20)

PDF
Have you tried listening?
Robert Nyman
 
PDF
Building for Your Next Billion - Google I/O 2017
Robert Nyman
 
PDF
Introduction to Google Daydream
Robert Nyman
 
PDF
Predictability for the Web
Robert Nyman
 
PDF
The Future of Progressive Web Apps - View Source conference, Berlin 2016
Robert Nyman
 
PDF
The Future of the Web - Cold Front conference 2016
Robert Nyman
 
PDF
The Future of Progressive Web Apps - Google for Indonesia
Robert Nyman
 
PDF
Google tech & products
Robert Nyman
 
PDF
Introduction to Progressive Web Apps, Google Developer Summit, Seoul - South ...
Robert Nyman
 
PDF
Progressive Web Apps keynote, Google Developer Summit, Tokyo, Japan
Robert Nyman
 
PDF
The web - What it has, what it lacks and where it must go - keynote at Riga D...
Robert Nyman
 
PDF
The web - What it has, what it lacks and where it must go - Bulgaria Web Summ...
Robert Nyman
 
PDF
The web - What it has, what it lacks and where it must go - Istanbul
Robert Nyman
 
PDF
The web - What it has, what it lacks and where it must go
Robert Nyman
 
PDF
Google, the future and possibilities
Robert Nyman
 
PDF
Developer Relations in the Nordics
Robert Nyman
 
PDF
What is Developer Relations?
Robert Nyman
 
PDF
Android TV Introduction - Stockholm Android TV meetup
Robert Nyman
 
PDF
Mobile phone trends, user data & developer climate - frontend.fi, Helsinki
Robert Nyman
 
PDF
Google & gaming, IGDA - Helsinki
Robert Nyman
 
Have you tried listening?
Robert Nyman
 
Building for Your Next Billion - Google I/O 2017
Robert Nyman
 
Introduction to Google Daydream
Robert Nyman
 
Predictability for the Web
Robert Nyman
 
The Future of Progressive Web Apps - View Source conference, Berlin 2016
Robert Nyman
 
The Future of the Web - Cold Front conference 2016
Robert Nyman
 
The Future of Progressive Web Apps - Google for Indonesia
Robert Nyman
 
Google tech & products
Robert Nyman
 
Introduction to Progressive Web Apps, Google Developer Summit, Seoul - South ...
Robert Nyman
 
Progressive Web Apps keynote, Google Developer Summit, Tokyo, Japan
Robert Nyman
 
The web - What it has, what it lacks and where it must go - keynote at Riga D...
Robert Nyman
 
The web - What it has, what it lacks and where it must go - Bulgaria Web Summ...
Robert Nyman
 
The web - What it has, what it lacks and where it must go - Istanbul
Robert Nyman
 
The web - What it has, what it lacks and where it must go
Robert Nyman
 
Google, the future and possibilities
Robert Nyman
 
Developer Relations in the Nordics
Robert Nyman
 
What is Developer Relations?
Robert Nyman
 
Android TV Introduction - Stockholm Android TV meetup
Robert Nyman
 
Mobile phone trends, user data & developer climate - frontend.fi, Helsinki
Robert Nyman
 
Google & gaming, IGDA - Helsinki
Robert Nyman
 
Ad

Recently uploaded (20)

PDF
Using FME to Develop Self-Service CAD Applications for a Major UK Police Force
Safe Software
 
PPTX
The Project Compass - GDG on Campus MSIT
dscmsitkol
 
PDF
Mastering Financial Management in Direct Selling
Epixel MLM Software
 
PDF
Smart Trailers 2025 Update with History and Overview
Paul Menig
 
PPTX
From Sci-Fi to Reality: Exploring AI Evolution
Svetlana Meissner
 
PDF
The Rise of AI and IoT in Mobile App Tech.pdf
IMG Global Infotech
 
PDF
[Newgen] NewgenONE Marvin Brochure 1.pdf
darshakparmar
 
PDF
Reverse Engineering of Security Products: Developing an Advanced Microsoft De...
nwbxhhcyjv
 
PPTX
Building Search Using OpenSearch: Limitations and Workarounds
Sease
 
PPTX
COMPARISON OF RASTER ANALYSIS TOOLS OF QGIS AND ARCGIS
Sharanya Sarkar
 
PDF
Empower Inclusion Through Accessible Java Applications
Ana-Maria Mihalceanu
 
DOCX
Cryptography Quiz: test your knowledge of this important security concept.
Rajni Bhardwaj Grover
 
PDF
CIFDAQ Market Wrap for the week of 4th July 2025
CIFDAQ
 
PDF
Staying Human in a Machine- Accelerated World
Catalin Jora
 
PPTX
WooCommerce Workshop: Bring Your Laptop
Laura Hartwig
 
PPTX
"Autonomy of LLM Agents: Current State and Future Prospects", Oles` Petriv
Fwdays
 
PDF
Exolore The Essential AI Tools in 2025.pdf
Srinivasan M
 
PDF
Transforming Utility Networks: Large-scale Data Migrations with FME
Safe Software
 
PDF
July Patch Tuesday
Ivanti
 
PPTX
OpenID AuthZEN - Analyst Briefing July 2025
David Brossard
 
Using FME to Develop Self-Service CAD Applications for a Major UK Police Force
Safe Software
 
The Project Compass - GDG on Campus MSIT
dscmsitkol
 
Mastering Financial Management in Direct Selling
Epixel MLM Software
 
Smart Trailers 2025 Update with History and Overview
Paul Menig
 
From Sci-Fi to Reality: Exploring AI Evolution
Svetlana Meissner
 
The Rise of AI and IoT in Mobile App Tech.pdf
IMG Global Infotech
 
[Newgen] NewgenONE Marvin Brochure 1.pdf
darshakparmar
 
Reverse Engineering of Security Products: Developing an Advanced Microsoft De...
nwbxhhcyjv
 
Building Search Using OpenSearch: Limitations and Workarounds
Sease
 
COMPARISON OF RASTER ANALYSIS TOOLS OF QGIS AND ARCGIS
Sharanya Sarkar
 
Empower Inclusion Through Accessible Java Applications
Ana-Maria Mihalceanu
 
Cryptography Quiz: test your knowledge of this important security concept.
Rajni Bhardwaj Grover
 
CIFDAQ Market Wrap for the week of 4th July 2025
CIFDAQ
 
Staying Human in a Machine- Accelerated World
Catalin Jora
 
WooCommerce Workshop: Bring Your Laptop
Laura Hartwig
 
"Autonomy of LLM Agents: Current State and Future Prospects", Oles` Petriv
Fwdays
 
Exolore The Essential AI Tools in 2025.pdf
Srinivasan M
 
Transforming Utility Networks: Large-scale Data Migrations with FME
Safe Software
 
July Patch Tuesday
Ivanti
 
OpenID AuthZEN - Analyst Briefing July 2025
David Brossard
 

New improvements for web developers - frontend.fi, Helsinki

  • 4. fulfilled = The action relating to the promise succeeded rejected = The action relating to the promise failed pending = Hasn't fulfilled or rejected yet settled = Has fulfilled or rejected
  • 5. var promise = new Promise(function(resolve, reject) {
 // do a thing, possibly async, then…
 
 if (/* everything turned out fine */) {
 resolve("Stuff worked!");
 }
 else {
 reject(Error("It broke"));
 }
 });
  • 6. promise.then(function(result) {
 console.log(result); // "Stuff worked!"
 }, function(err) {
 console.log(err); // Error: "It broke"
 });
  • 8. XMLHttpRequest example function reqListener() { 
 var data = JSON.parse(this.responseText); 
 console.log(data); 
 }
 
 function reqError(err) { 
 console.log('Fetch Error :-S', err); 
 }
 
 var oReq = new XMLHttpRequest(); 
 oReq.onload = reqListener; 
 oReq.onerror = reqError; 
 oReq.open('get', './api/some.json', true); 
 oReq.send();
  • 9. fetch() version fetch('./api/some.json') 
 .then( 
 function(response) { 
 if (response.status !== 200) { 
 console.log('Looks like there was a problem. Status Code: ' + 
 response.status); 
 return; 
 }
 
 // Examine the text in the response 
 response.json().then(function(data) { 
 console.log(data); 
 }); 
 } 
 ) 
 .catch(function(err) { 
 console.log('Fetch Error :-S', err); 
 });
  • 10. Response metadata fetch('users.json').then(function(response) { 
 console.log(response.headers.get('Content-Type')); 
 console.log(response.headers.get('Date'));
 
 console.log(response.status); 
 console.log(response.statusText); 
 console.log(response.type); 
 console.log(response.url); 
 });
  • 13. Defining modes fetch('http://some-site.com/cors-enabled/some.json', {mode: 'cors'}) 
 .then(function(response) { 
 return response.text(); 
 }) 
 .then(function(text) { 
 console.log('Request successful', text); 
 }) 
 .catch(function(error) { 
 log('Request failed', error) 
 });
  • 15. It's a JavaScript Worker, so it can't access the DOM directly. Instead responds to postMessages Service worker is a programmable network proxy It will be terminated when not in use, and restarted when it's next needed Makes extensive use of Promises
  • 19. Register and Installing a Service Worker if ('serviceWorker' in navigator) {
 navigator.serviceWorker.register('/sw.js').then(function(registration) {
 // Registration was successful
 console.log('ServiceWorker registration successful with scope: ', registration.scope);
 }).catch(function(err) {
 // registration failed :(
 console.log('ServiceWorker registration failed: ', err);
 });
 }
  • 21. // The files we want to cache
 var urlsToCache = [
 '/',
 '/styles/main.css',
 '/script/main.js'
 ];
 
 // Set the callback for the install step
 self.addEventListener('install', function(event) {
 // Perform install steps
 }); Installing
  • 22. Inside our install callback: 1. Open a cache 2. Cache our files 3. Confirm whether all the required assets are cached or not
  • 23. Install callback var CACHE_NAME = 'my-site-cache-v1';
 var urlsToCache = [
 '/',
 '/styles/main.css',
 '/script/main.js'
 ];
 
 self.addEventListener('install', function(event) {
 // Perform install steps
 event.waitUntil(
 caches.open(CACHE_NAME)
 .then(function(cache) {
 console.log('Opened cache');
 return cache.addAll(urlsToCache);
 })
 );
 });
  • 24. self.addEventListener('fetch', function(event) {
 event.respondWith(
 caches.match(event.request)
 .then(function(response) {
 // Cache hit - return response
 if (response) {
 return response;
 }
 
 return fetch(event.request);
 }
 )
 );
 }); Caching and Returning Requests
  • 25. self.addEventListener('fetch', function(event) {
 event.respondWith(
 caches.match(event.request)
 .then(function(response) {
 // Cache hit - return response
 if (response) {
 return response;
 }
 
 // IMPORTANT: Clone the request. A request is a stream and
 // can only be consumed once. Since we are consuming this
 // once by cache and once by the browser for fetch, we need
 // to clone the response
 var fetchRequest = event.request.clone();
 
 return fetch(fetchRequest).then(
 function(response) {
 // Check if we received a valid response
 if(!response || response.status !== 200 || response.type !== 'basic') {
 return response;
 }
 
 // IMPORTANT: Clone the response. A response is a stream
 // and because we want the browser to consume the response
 // as well as the cache consuming the response, we need
 // to clone it so we have 2 stream.
 var responseToCache = response.clone();
 
 caches.open(CACHE_NAME)
 .then(function(cache) {
 cache.put(event.request, responseToCache);
 });
 
 return response;
 }
 );
 })
 );
 }); Caching new requests cumulatively
  • 27. 1. Update your service worker JavaScript file. 2. Your new service worker will be started and the install event will be fired. 3. New Service Worker will enter a "waiting" state 4. When open pages are closed, the old Service Worker will be killed - new service worker will take control. 5. Once new Service Worker takes control, its activate event will be fired. Updating a Service Worker
  • 28. Cache management & whitelists self.addEventListener('activate', function(event) {
 
 var cacheWhitelist = ['pages-cache-v1', 'blog-posts-cache-v1'];
 
 event.waitUntil(
 caches.keys().then(function(cacheNames) {
 return Promise.all(
 cacheNames.map(function(cacheName) {
 if (cacheWhitelist.indexOf(cacheName) === -1) {
 return caches.delete(cacheName);
 }
 })
 );
 })
 );
 });
  • 31. <button class="js-push-button" disabled> 
 Enable Push Messages 
 </button>
  • 32. // Are Notifications supported in the service worker? 
 if (!('showNotification' in ServiceWorkerRegistration.prototype)) { 
 console.warn('Notifications aren't supported.'); 
 return; 
 }
  • 33. // Check the current Notification permission. 
 // If its denied, it's a permanent block until the 
 // user changes the permission 
 if (Notification.permission === 'denied') { 
 console.warn('The user has blocked notifications.'); 
 return; 
 }
  • 34. // Check if push messaging is supported 
 if (!('PushManager' in window)) { 
 console.warn('Push messaging isn't supported.'); 
 return; 
 }
  • 35. // We need the service worker registration to check for a subscription 
 navigator.serviceWorker.ready.then(function(serviceWorkerRegistration) { 
 // Do we already have a push message subscription? 
 serviceWorkerRegistration.pushManager.getSubscription() 
 .then(function(subscription) { 
 // Enable any UI which subscribes / unsubscribes from 
 // push messages. 
 var pushButton = document.querySelector('.js-push-button'); 
 pushButton.disabled = false;
 
 if (!subscription) { 
 // We aren't subscribed to push, so set UI 
 // to allow the user to enable push 
 return; 
 }
 
 // Keep your server in sync with the latest subscriptionId
 sendSubscriptionToServer(subscription);
 
 // Set your UI to show they have subscribed for 
 // push messages 
 pushButton.textContent = 'Disable Push Messages'; 
 isPushEnabled = true; 
 }) 
 .catch(function(err) { 
 console.warn('Error during getSubscription()', err); 
 }); 
 });
  • 36. { 
 "name": "Push Demo", 
 "short_name": "Push Demo", 
 "icons": [{ 
 "src": "images/icon-192x192.png", 
 "sizes": "192x192",
 "type": "image/png" 
 }], 
 "start_url": "/index.html?homescreen=1", 
 "display": "standalone", 
 "gcm_sender_id": "123456789012", 
 "gcm_user_visible_only": true 
 } <link rel="manifest" href="manifest.json">
  • 38. Cache management & whitelistsApp Install Banners
  • 39. App Install Banners prerequisites You have a web app manifest file You have a service worker registered on your site. We recommend a simple custom offline page service worker Your site is served over HTTPS (you need a service worker after all) The user has visited your site twice over two separate days during the course of two weeks.
  • 40. "You can do all of this?"