Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
Web improvements @robertnyman
Promises
fulfilled = The action relating to the promise succeeded
rejected = The action relating to the promise failed
pending = Has...
var promise = new Promise(function(resolve, reject) {

// do a thing, possibly async, then…



if (/* everything turned ou...
promise.then(function(result) {

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

}, function(err) {

console.log(err); // Error: ...
fetch()
XMLHttpRequest example
function reqListener() { 

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

console.log(data); 

}



fu...
fetch() version
fetch('./api/some.json') 

.then( 

function(response) { 

if (response.status !== 200) { 

console.log('L...
Response metadata
fetch('users.json').then(function(response) { 

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

con...
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 ...
Service Workers
It's a JavaScript Worker, so it can't access the DOM
directly. Instead responds to postMessages
Service worker is a progra...
No Service Worker
HTTPS is Needed
Register and Installing a Service Worker
if ('serviceWorker' in navigator) {

navigator.serviceWorker.register('/sw.js').t...
chrome://inspect/#service-workers
// The files we want to cache

var urlsToCache = [

'/',

'/styles/main.css',

'/script/main.js'

];



// Set the callbac...
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('fetch', function(event) {

event.respondWith(

caches.match(event.request)

.then(function(response...
self.addEventListener('fetch', function(event) {

event.respondWith(

caches.match(event.request)

.then(function(response...
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 fire...
Cache management & whitelists
self.addEventListener('activate', function(event) {



var cacheWhitelist = ['pages-cache-v1...
Push notifications
<button class="js-push-button" disabled> 

Enable Push Messages 

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

if (!('showNotification' in ServiceWorkerRegistration.prototype)) ...
// Check the current Notification permission. 

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

// user changes the p...
// Check if push messaging is supported 

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

console.warn('Push messaging isn't supported...
// We need the service worker registration to check for a subscription 

navigator.serviceWorker.ready.then(function(servi...
{ 

"name": "Push Demo", 

"short_name": "Push Demo", 

"icons": [{ 

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

"sizes": "192x19...
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 re...
"You can do all of this?"
Robert Nyman
robertnyman.com

rnyman@google.com

Google
@robertnyman
New improvements for web developers - frontend.fi, Helsinki
New improvements for web developers - frontend.fi, Helsinki
New improvements for web developers - frontend.fi, Helsinki
New improvements for web developers - frontend.fi, Helsinki
Upcoming SlideShare
Loading in …5
×

New improvements for web developers - frontend.fi, Helsinki

6,366 views

Published on

New improvements for web developers - Promises, fetch, Service Workers, Push notifications, Add to Homescreen.

Slides from a talk I gave at #frontendfi in Helsinki yesterday

Published in: Technology

New improvements for web developers - frontend.fi, Helsinki

  1. Web improvements @robertnyman
  2. Promises
  3. 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
  4. 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"));
 }
 });
  5. promise.then(function(result) {
 console.log(result); // "Stuff worked!"
 }, function(err) {
 console.log(err); // Error: "It broke"
 });
  6. fetch()
  7. 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();
  8. 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); 
 });
  9. 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); 
 });
  10. Response Types basic cors opaque
  11. Defining modes same-origin cors cors-with-forced-preflight no-cors
  12. 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) 
 });
  13. Service Workers
  14. 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
  15. No Service Worker
  16. HTTPS is Needed
  17. 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);
 });
 }
  18. chrome://inspect/#service-workers
  19. // 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
  20. Inside our install callback: 1. Open a cache 2. Cache our files 3. Confirm whether all the required assets are cached or not
  21. 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);
 })
 );
 });
  22. 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
  23. 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
  24. Updating a Service Worker
  25. 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
  26. 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);
 }
 })
 );
 })
 );
 });
  27. Push notifications
  28. <button class="js-push-button" disabled> 
 Enable Push Messages 
 </button>
  29. // Are Notifications supported in the service worker? 
 if (!('showNotification' in ServiceWorkerRegistration.prototype)) { 
 console.warn('Notifications aren't supported.'); 
 return; 
 }
  30. // 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; 
 }
  31. // Check if push messaging is supported 
 if (!('PushManager' in window)) { 
 console.warn('Push messaging isn't supported.'); 
 return; 
 }
  32. // 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); 
 }); 
 });
  33. { 
 "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">
  34. Add to Homescreen
  35. Cache management & whitelistsApp Install Banners
  36. 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.
  37. "You can do all of this?"
  38. Robert Nyman robertnyman.com rnyman@google.com Google @robertnyman

×