sábado, 31 de diciembre de 2016

Entendiendo la Web notification API

La Web notification API nos permite mandar notificaciones a los usuario a como lo hacen las app nativas.

Para usar primero necesitamos que el usuario de permiso con el siguiente codigo:


Notification.requestPermission(function(status) {  // status is "granted", if accepted by user
    var notificationMsg = new Notification('Title', { 
       body: 'I am the body text!'
    }); 
});

Puesdes ver la demo en este link:  https://saulburgos.github.io/practices/2017/webnotification/

 Una vez con el permiso, usamos el objecto Notificacion para crear un instancia del mensaje que queremos usar. Mas adelante si necesitamos verificar este permiso de nuevo podemos consulta la propiedad "permission", que puede tener los valores de : "default, granted, denied"

Notification.permission

Esta API comunmente se usa en conjunto con los services worker y push API, para notificar de la manera en como lo hacen las app nativas cuando no tienes la app abierta

links
https://developer.mozilla.org/en-US/docs/Web/API/Notifications_API/Using_the_Notifications_API
https://developer.mozilla.org/en/docs/Web/API/notification

viernes, 30 de diciembre de 2016

¿ Como saber con javascript si estas online ó offline ?

El objeto "navigation" puede ayudarnos con esto:

https://developer.mozilla.org/en-US/docs/Web/API/NavigatorOnLine/onLine

 Solo tenemos que consultar esta propiedad que nos devolvera un valor true/false.

window.navigator.onLine;

Su uso es:

if (navigator.onLine) {
  console.log('online');
} else {
  console.log('offline');
}
 

Tambien podemos escuchar un eventos para saber cuando hay conexión :

window.addEventListener("offline", function(e) { 
  console.log("offline");
});

window.addEventListener("online", function(e) { 
  console.log("online"); 
});

links

https://developer.mozilla.org/en-US/docs/Web/API/NavigatorOnLine/onLine



jueves, 29 de diciembre de 2016

Entendiendo la Cache API


Comunmente esta API es usada en conjunto con la API Service worker, pero puedes usarlo independientemente aunque no he encontrado un ejemplo de su uso fuera de esta API. Segun la definicion se usa para guardar objectos "Request" y "Response", esto significa que puedes dar las peticiones que haces al server y tambien las respuestas del server.

Una parte importante a saber que casi todos los metodos de esta API usan promesas. Para crear un espacio donde cachear todos nuestros assets solo necesitamos llamar este metodo del objecto "caches"

caches.open('test-cache').then(function(cache) {
  // Cache is created and accessible
});

El nombre 'test-cache' es una namespace o identificador de la cache que hemos creado. De esta manera podemos usarla luego.

Para agregar elementos a la cache creada se usa comunmente los metodos "Add" y "addAll".

cache.add('/sw-test/index.html').then(function() {
  //request have been added to the cache
});

cache.addAll(['/', '/images/logo.png']).then(function() {
  //requests have been added to the cache
});

La diferencia es que en la segunda se pasa un arreglo de urls. Algo que destacar aqui es que usar el metodo "add" es lo mismo que usar fetch de formal normal con put de esta manera:

fetch(url).then(function (response) {
  if (!response.ok) {
    throw new TypeError('bad response status');
  }
  return cache.put(url, response);
});

O peticiones personalizadas con el object "Request" de esta forma:

cache.add(new Request('/page/1', { /* request options */ }));
 
"add" and "addAll" son como atajos del metodo "put" por que con este metodo pones en cache usando key/value de esta manera:

fetch(url).then(function (response) {
  return cache.put(url, response);
});

Revisar la cache

 Para revisar que hemos puesto en la cache primero necesitamos abrirla y despues explorar los elementos usando el metodo "keys"de esta manera:

caches.open('test-cache').then(function(cache) { 
 
  cache.keys().then(function(cachedRequests) { 
    // [] Array of all of caches keys
  });
});

Para buscar dentro se usan los metodos "match", "matchAll":

caches.open('test-cache').then(function(cache) {
  cache.match('/page/1').then(function(matchedResponse) {
    console.log(matchedResponse);
  });
});

En el ejemplo anterior, estamos buscando el objecto en cache que correspondo con la peticion a 'page/1'

Otros usos comunes serian leer y buscar:

caches.open('test-cache').then(function(cache) {
  cache.delete('/page/1');
});

caches.keys().then(function(cacheKeys) { 
  console.log(cacheKeys); // Get all the namespace created
});

caches.delete('test-cache').then(function() { 
  console.log('Cache successfully deleted!');  
});

Dentro de un service worker, el proceso seria algo asi:

  • El service worker intercepta todas las peticiones al server, ya sean ajax o cargar otras paginas web.
  • Una vez interceptada la peticion, revisamos en nuestra cache si esa peticion ya esta en la cache
  • Si es asi devolvemos el objecto en cache.
  • Si no dejamos que la peticion siga su curso, al terminar la metemos al cache.

Ejemplo de esto:

//trigger on url changes and requests to the server
serviceWorker.addEventListener('fetch', function(event) { 
 //search in the cache for the request that is in progress
 var cacheFound = caches.match(event.request).then(function(response) {
  
  if (response) {
   //return the object cached
    return response;
  } else {
   //if not, we make the normal request
   return fetch(event.request); 
  }  
 });

 //we pass the promise 
 event.respondWith(cacheFound);

});

Aqui he hecho un ejemplo del uso de la cache API sin un service worker

Links

https://developer.mozilla.org/en-US/docs/Web/API/Cache
https://davidwalsh.name/cache



Entendiendo la Promise API

Las promesas son ahora la manera preferida de trabajar y en el futuro sera muy pocos los casos en los que necesitaras una callback. jQuery tiene su propio sistema de promesas.

Pero ahora tenemos una API promise nativa que podemos usar. Su uso es muy sencillo:

var promise = new Promise(function(resolveFn, rejectFn) { 
 
 //you can do here operations and later decided if resolve or reject the promise
 //using the objects
 setTimeout(function() { 
  resolveFn(10);

 }, 3000);

});

//when is resolve
promise.then(function(result) {
 console.log(result);
});

//when is rejected
promise.catch(function(result) {
 console.log(result);
});

Despues de haber instanciado el objecto "Promise" tienes los metodos "resolveFn" y "rejectFn" los cuales puedes ejecutar cuando tu quieras en un futuro, los cuales van a ejecutar los metodos pasados a "then" y "catch".

Un interesante metodo de "Promise" es "all", el cual recibe un arreglo de promesas y ejecuta "then" cuando todas han sido "resolve".

Promise.all([promise1, promise2]).then(function(results) {
 // Both promises resolved
})
.catch(function(error) {
 // One or more promises was rejected
});

Link

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
https://davidwalsh.name/promises



Entendiendo la Fetch API

Ahora ya no usamos Ajax para hacer peticiones al server ahora usamos Fetch. Por que ? por que nos permite usar promesas en lugar de callbacks, permitiendo un codigo mas limpio.

Una peticion con fetch basica es de la siguiente manera:

fetch('./api/some.json').then(function(respond){
    //exito
}).catch(function(err) { 
    //Error en la peticion
});

La promesa se mira en accion con los metodos "then" y "catch", a los cuales se le pasa metodos para ser ejecutados cuando terminen.

Then : Es ejecutado cuando la peticion termina correctamente.
catch: Es ejecutado cuando en la peticion ocurrio un error.

Fetch retorna un objecto stream cuando la peticion es exitosa, el cual tiene muchos metodos para usar. Puedes consultarlos aqui. El ejemplo completo seria asi:

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); 
});

Otras propiedades interesantes del objecto response son:

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);  
});

El objecto response puede ser de varios tipos para una mejor descripcion visita este link.


Adicionalmente puedes usar los objectos "Request" y "Header" para personalizar los peticiones fetch. Tomando un ejemplo de david walsh, seria asi:

// Create an empty Headers instance
var headers = new Headers();

// Add a few headers
headers.append('Content-Type', 'text/plain');
headers.append('X-My-Custom-Header', 'CustomValue');

// Check, get, and set header values
headers.has('Content-Type'); // true
headers.get('Content-Type'); // "text/plain"
headers.set('Content-Type', 'application/json');

// Delete a header
headers.delete('X-My-Custom-Header');

// Add initial values
var headers = new Headers({
  'Content-Type': 'text/plain',
  'X-My-Custom-Header': 'CustomValue'
});

var request = new Request('https://davidwalsh.name/some-url', {
  headers: new Headers({
    'Content-Type': 'text/plain'
  })
});

fetch(request).then(function() { /* handle response */ });

Es una manera facil y alternativa del uso de ajax.

Links:

https://davidwalsh.name/fetch
https://developers.google.com/web/updates/2015/03/introduction-to-fetch
https://developer.mozilla.org/en/docs/Web/API/Fetch_API
https://hacks.mozilla.org/2015/03/this-api-is-so-fetching/