Capítulo 16 API Offline
16.1 Caché
Los días de trabajar desconectado han llegado a su fin. Debido a que este capítulo presenta API Offline (la API para trabajar desconectados), esta declaración puede resultar contradictoria, pero analicémoslo por un momento. Hemos trabajado desconectados casi toda nuestra vida. Las aplicaciones de escritorio fueron nuestra herramienta primaria de producción. Y ahora, de repente, la web ha emergido como la nueva plataforma de trabajo. Aplicaciones en línea se vuelven más y más complejas, y HTML5 está haciendo la batalla entre estos dos mundos más dura que nunca. Bases de datos, acceso a archivos, almacenamiento, herramientas gráficas, edición de imagen y video, y multiprocesamiento son, entre otras, características esenciales para una aplicación que ahora se encuentran disponibles en la web. Nuestra actividad diaria gira cada vez más en torno a la web, y nuestro ámbito de producción se encuentra en la red. Los días de trabajar desconectados son historia.
Sin embargo, a medida que esta transición continúa, las aplicaciones web se vuelven más sofisticadas, requiriendo archivos más grandes y mayor tiempo de descarga. Para cuando las aplicaciones en la web reemplacen definitivamente a las aplicaciones de escritorio, trabajar en línea será imposible. Los usuarios no podrán descargar varios megabytes de archivos cada vez que necesiten usar una aplicación y no podrán contar con tener conexión a la red disponible todo el tiempo. Las aplicaciones que no requieren Internet pronto desaparecerán, pero bajo las actuales circunstancias las aplicaciones en línea están destinadas a fracasar.
Offline API llega para ayudarnos a resolver este dilema. Básicamente, esta API provee la alternativa de almacenar las aplicaciones y archivos web en el ordenador del usuario para uso futuro. Un solo acceso es suficiente para descargar todos los archivos requeridos y ejecutar la aplicación en todo momento, con o sin conexión a Internet. Una vez que los archivos son descargados, la aplicación funciona en el navegador usando este caché (los archivos almacenados en el ordenador), como lo haría una aplicación de escritorio, independientemente de lo que pase con el servidor o la conexión.
El archivo manifiesto
Una aplicación web o un sitio web sofisticado consistirá en varios archivos, pero no todos ellos serán requeridos para ejecutar la aplicación y tampoco será necesario almacenarlos a todos en el ordenador del usuario. La API asigna un archivo específico para declarar la lista de archivos que la aplicación necesita para trabajar sin conexión. Este es solo un archivo de texto llamado «manifiesto» (manifest), conteniendo una lista de URLs que apuntan a la ubicación de los archivos requeridos. El manifiesto puede ser creado con cualquier editor de texto, y debe comenzar con la línea cache manifest, como en el siguiente ejemplo:
CACHE MANIFEST
cache.html
cache.css
cache.j s
Listado 16-1. Archivo manifiesto.
El manifiesto deberá ser grabado con la extensión .manifest y deberá incluir debajo de cache manifest todos los archivos que la aplicación necesita para trabajar desde el ordenador del usuario sin solicitar ningún recurso externo. En nuestro ejemplo, tenemos el archivo cache.html como el documento principal de la aplicación, el archivo cache.css con los estilos CSS y el archivo cache.js conteniendo los códigos Javascript.
Del mismo modo que necesitamos especificar los archivos requeridos para trabajar desconectados, también podríamos necesitar declarar explícitamente aquellos que se encuentran solo disponibles cuando estamos conectados. Este podría ser el caso para algunas partes de la aplicación que solo serán útiles cuando tenemos acceso a Internet (por ejemplo, una sala de chat para consultas).
Para identificar los tipos de archivos listados en el archivo manifiesto, la API introduce tres categorías:
CACHE Esta es la categoría por defecto. Todos los archivos en esta categoría serán almacenados en el ordenador del usuario para uso futuro.
NETWORK Esta categoría es considerada como una lista de aprobación; todos los archivos en su interior solo se encuentran disponibles en línea.
FALLBACK Esta categoría es para archivos que podría ser útil obtener del servidor cuando estamos conectados, pero que pueden ser reemplazados por una versión en el caché. Si el navegador detecta que hay conexión, intentará usar el archivo original en el servidor, en caso contrario, será usado en su lugar el alternativo ubicado en el ordenador del usuario.
Usando categorías, nuestro archivo manifiesto podría ser similar al siguiente:
CACHE: cache.html cache.css cache.j s
NETWORK: chat.html
FALLBACK:
noticias.html sinnoticias.html
Listado 16-2. Declarando archivos por categoría.
En el nuevo archivo manifiesto del Listado 16-2, los archivos son listados bajo la categoría correspondiente. Los tres archivos en la categoría cache serán descargados, almacenados en el ordenador del usuario y usados para esta aplicación de ahora en más (a menos que especifiquemos algo diferente más adelante). El archivo chat.html especificado en la categoría network estará solo disponible cuando el navegador tenga acceso a Internet. Y por último, el archivo noticias.html dentro de la categoría fallback será accedido desde el servidor cuando exista conexión a la red, o reemplazado por el archivo sinnoticias.html ubicado en el ordenador del usuario en caso contrario. Del mismo modo que los archivos dentro de la categoría cache, el archivo sinnoticias.html es incluido en el caché y por lo tanto almacenado en el ordenador del usuario para estar disponible cuando sea requerido.
La categoría fallback es útil no solo para reemplazar archivos individuales sino también para proveer alternativas para directorios completos. Por ejemplo, la línea / sinconexion.html reemplazará cualquier archivo que no esté disponible en el caché por el archivo sinconexion.html. Esta es una forma simple de desviar a los usuarios hacia un documento que les recomienda conectarse a Internet cuando intentan acceder a una parte de la aplicación que no está disponible sin conexión.
Los comentarios pueden ser agregados al manifiesto usando el símbolo # (uno por cada línea de comentario). Debido a que la lista de archivos es ordenada en categorías, puede parecer inútil el agregado de comentarios, pero son importantes, especialmente a la hora de realizar actualizaciones en el caché (descargar nuevas versiones de archivos). El archivo manifiesto no solo declara qué archivos serán incluidos en el caché, sino cuándo. Cada vez que los archivos de la aplicación son actualizados, no hay forma en la que el navegador pueda saberlo excepto a través del archivo manifiesto. Si los archivos actualizados son los mismos y ninguno fue agregado a la lista, el archivo manifiesto lucirá exactamente igual que antes, entonces el navegador no podrá reconocer la diferencia y seguirá usando los archivos viejos que ya se encuentran en el caché. Sin embargo, podemos forzar al navegador a descargar nuevamente los archivos de la aplicación indicando la existencia de una actualización por medio del agregado de comentarios. Normalmente, un solo comentario
con la fecha de la última actualización (o cualquier otro dato) será suficiente, como es mostrado en el siguiente ejemplo:
Listado 16-3. Nuevo comentario para informar sobre actualizaciones.
Supongamos que agregamos más código a las funciones actuales del archivo cache. j s. Los usuarios tendrán el archivo dentro del caché en sus ordenadores y los navegadores usarán esta vieja versión en lugar de la nueva. Cambiando la fecha al final del archivo manifiesto o agregando nuevos comentarios informaremos al navegador acerca de la actualización y todos los archivos necesarios para trabajar sin conexión serán nuevamente descargados, incluyendo la versión mejorada del archivo cache.js. Luego de que el caché es actualizado, el navegador ejecutará la aplicación usando los nuevos archivos en el ordenador del usuario.
Luego de seleccionar todos los archivos necesarios para que la aplicación pueda funcionar sin conexión a Internet e incluir la lista completa de URLs apuntando a estos archivos, tenemos que cargar el manifiesto desde nuestros documentos. La API provee un nuevo atributo para el elemento <html> que indica la ubicación de este archivo:
CACHE MANIFEST
CACHE: cache.html cache.css cache.j s
NETWORK: chat.html
FALLBACK:
noticias.html sinnoticias.html # fecha 2011/08/10
<!DOCTYPE html>
<html lang=»es» manifest=»micache.manifest»> <head>
<title>Offline API</title>
<link rel=»stylesheet» href=»cache.css»> <script src=»cache.j s»></script>
</head>
<body>
<section id=»cajadatos»>
Aplicación para trabajar sin conexión </section>
</body>
</html>
Listado 16-4. Cargando el archivo manifiesto.
El Listado 16-4 muestra un pequeño documento HTML que incluye el atributo manifest en el elemento <html>. El atributo manifest indica la ubicación del archivo manifiesto necesario para generar el caché de la aplicación. Como puede ver, nada cambia en el resto del documento: los archivos para estilos CSS y códigos Javascript son incluidos como siempre, independientemente del contenido del archivo manifiesto.
El manifiesto debe ser grabado con la extensión .manifest y el nombre que desee (en nuestro ejemplo, micache). Cada vez que el navegador encuentra el atributo manifest en un documento, intentará descargar el archivo manifiesto en primer lugar y luego todos los archivos listados en su interior. El atributo manifest debe ser incluido en cada documento HTML que tiene que ser parte del caché de la aplicación. El proceso es transparente para el usuario y puede ser controlado desde código Javascript usando la API, como veremos pronto.
Además de la extensión y la estructura interna del archivo manifiesto, existe otro requisito importante a considerar. El archivo manifiesto debe ser provisto por los servidores con el tipo MIME apropiado. Cada archivo posee un tipo MIME asociado para indicar el formato de su contenido. Por ejemplo, el tipo MIME para un archivo HTML es text/html. Un archivo manifiesto debe ser provisto usando el tipo text/cache- manifest o el navegador devolverá un error.
IMPORTANTE: El tipo MIME text/cache-manifest no forma parte de la configuración por defecto de ningún servidor en este momento. Usted deberá agregarlo a su servidor manualmente. Cómo incluir este nuevo tipo de archivo depende de la clase de servidor con la que trabaje. Para algunas versiones de Apache, por ejemplo, el agregado de la siguiente línea en el archivo httpd.conf será suficiente para comenzar a despachar estos archivos con el tipo MIME apropiado:AddType text/cache-manifest .manifest.
El archivo manifiesto por sí mismo debería ser suficiente para generar un caché para sitios webs pequeños o códigos simples, pero aplicaciones complejas demandan mayor control. El archivo manifiesto declara los archivos necesarios para el caché, pero no puede informar sobre cuántos de estos archivos ya fueron descargados, o los errores encontrados en el proceso, o cuándo una actualización está lista para ser usada, entre otras importantes situaciones. Considerando estos posibles escenarios, la API provee el nuevo objeto ApplicationCache con métodos, propiedades y eventos para controlar todo el proceso.
Probablemente el evento más importante del objeto ApplicationCache es error. Si un error ocurre durante el proceso de lectura de archivos desde el servidor, por ejemplo, el caché necesario para que la aplicación trabaje fuera de línea no podrá ser creado o actualizado. Es extremadamente importante reconocer estas situaciones y actuar de acuerdo a las circunstancias.
Usando el documento HTML presentado en el Listado 16-4, vamos a construir una pequeña aplicación para entender cómo funciona este evento.
function iniciar(){
var cache=window.applicationCache;
cache.addEventListener(‘error’, errores, false);
}
function errores(){
alert(‘error’);
}
window.addEventListener(‘load’, iniciar, false);
Listado 16-5. Controlando errores.
El atributo applicationCache para el objeto Window usado en el código del Listado 16-5 retorna el objeto ApplicationCache para este documento. Luego de almacenar una referencia al objeto dentro de la variable cache, agregamos una escucha para el evento error. Esta escucha llamará a la función errores () cuando el evento es disparado y un mensaje de alerta será mostrado informando el error.
Hágalo usted mismo: Cree un archivo HTML con el código del Listado 16-4, un archivo Javascript llamado cache.j s con el código del Listado 16-5, y un archivo manifiesto llamado micache.manifest. De acuerdo a lo que hemos estudiado, deberá incluir en el archivo manifiesto la lista de archivos necesarios para el caché dentro de la categoría cache. Para nuestro ejemplo, estos archivos son el archivo HTML, el archivo cache .js y el archivo cache. css (los estilos para este último archivo son presentados en el Listado 16-6). Suba estos archivos a su servidor y abra el documento HTML en su navegador. Si elimina el archivo manifiesto u olvida agregar el tipo MIME correspondiente para este archivo en su servidor, el evento error será disparado. También puede interrumpir el acceso a Internet o usar la opción Trabajar sin Conexión ofrecida en Firefox para ver la aplicación funcionando sin conexión y desde el nuevo caché.
El archivo CSS tiene solo que incluir estilos para el elemento <section> de nuestra plantilla. Puede crear los suyos o utilizar los siguientes:
#caj adatos{
width: 500px;
height: 300px;
margin: 10px;
padding: 10px;
border: 1px solid #999999;
}
Listado 16-6. Regla CSS para la cajadatos.
Online y offline
Una nueva propiedad para el objeto Navigator fue incorporada. Se llama onLine e indica el actual estado de la conexión. Esta propiedad tiene dos eventos asociados que serán disparados cuando su valor cambie. La propiedad y los eventos no son parte del objeto ApplicationCache, pero son útiles para esta API.
online Este evento es disparado cuando el valor de la propiedad onLine cambia a true (verdadero).
offline Este evento es disparado cuando el valor de la propiedad onLine cambia a false (falso).
El siguiente es un ejemplo de cómo usarlos:
function iniciar(){
caj adatos=document.getElementById(‘caj adatos’);
window.addEventListener(‘online’ , function(){ estado(1); },
false);
window.addEventListener(‘offline’, function(){ estado(2); },
false);
}
function estado(valor){ switch(valor){
case 1:
caj adatos.innerHTML+='<br>Estamos Conectados’; break; case 2:
caj adatos.innerHTML+='<br>Estamos Desconectados’; break;
}
}
window.addEventListener(‘load’, iniciar, false);
Listado 16-7. Controlando el estado de la conexión.
En el código del Listado 16-7, usamos funciones anónimas para manejar eventos y enviar un valor a la función estado() con la intención de mostrar el mensaje correspondiente en la cajadatos. Los eventos serán disparados cada vez que el valor de la propiedad onLine cambie.
IMPORTANTE: No hay garantía alguna de que la propiedad retorne siempre el valor adecuado. Escuchar a estos eventos en un ordenador de escritorio probablemente no producirá ningún efecto, incluso cuando el equipo sea completamente desconectado de Internet. Para probar este ejemplo, recomendamos usar la opción Trabajar sin Conexión ofrecida por Firefox.
Hágalo usted mismo: Use los mismos archivos HTML y CSS de ejemplos previos. Copie el código del Listado 16-7 en el archivo cache. j s. Usando Firefox, elimine el caché de su aplicación y abra el documento HTML. Para probar el funcionamiento de los eventos, puede usar la opción Trabajar sin Conexión. Cada vez que active o desactive esta opción, la condición cambiará y un nuevo mensaje será automáticamente agregado a la caj adatos.
Crear o actualizar el caché puede tomar desde algunos segundos hasta varios minutos, dependiendo del tamaño de los archivos que deben ser descargados. El proceso pasa por diferentes estados de acuerdo con lo que el navegador es capaz de hacer en cada momento. En una actualización normal, por ejemplo, el navegador intentará primero leer el archivo manifiesto para buscar por posibles actualizaciones, descargará todos los archivos listados en el manifiesto (si la actualización existe) e informará cuando el proceso es finalizado. Para ofrecer información sobre cada paso en el proceso, la API ofrece la propiedad status. Esta propiedad puede tomar los valores siguientes:
UNCACHED (valor 0) Este valor indica que ningún caché fue creado aún para la aplicación. IDLE (valor 1) Este valor indica que el caché de la aplicación es el más nuevo disponible y no es obsoleto.
CHECKING (valor 2) Este valor indica que el navegador está comprobando la existencia de nuevas actualizaciones.
DOWNLOADING (valor 3) Este valor indica que los archivos para el caché están siendo descargados.
UPDATEREADY (valor 4) Este valor indica que el caché de la aplicación está disponible y no es obsoleto, pero no es el más nuevo (una actualización está lista para reemplazarlo). OBSOLETE (valor 5) Este valor indica que el caché actual es obsoleto.
Podemos controlar el valor de la propiedad status en cualquier momento, pero es mejor usar los eventos provisto por el objeto ApplicationCache para controlar el estado del proceso y el caché. Los siguientes eventos son normalmente disparados en secuencia, y algunos de ellos están asociados a un estado específico del caché de la aplicación:
checking Este evento es disparado cuando el navegador está controlando por la existencia de actualizaciones.
noupdate Este evento es disparado cuando no fueron encontrados cambios en el archivo manifiesto.
downloading Este evento es disparado cuando el navegador encuentra una nueva actualización y comienza a descargar los archivos. cached Este evento es disparado cuando el caché está listo.
updateready Este evento es disparado cuando el proceso de descarga para una actualización fue completado.
obsolete Este evento es disparado cuando el archivo manifiesto ya no está disponible y el caché está siendo eliminado.
El siguiente ejemplo nos ayudará a entender este proceso. Mediante este código, cada vez que un evento es disparado, un mensaje es agregado a la cajadatos con el valor del evento y el de la propiedad status.
function iniciar(){
caj adatos=document.getElementByld(‘caj adatos’);
cache=window.applicationCache;
cache.addEventListener(‘checking’, function(){ mostrar(1); },
false);
cache.addEventListener(‘downloading’, function(){ mostrar(2); },
false);
cache.addEventListener(‘cached’, function(){ mostrar(3); },
false);
cache.addEventListener(‘updateready’, function(){ mostrar(4); },
false);
cache.addEventListener(‘obsolete’, function(){ mostrar(5); },
false);
}
function mostrar(valor){
caj adatos.innerHTML+='<br>Estado: ‘+cache.status;
cajadatos.innerHTML+=’ | Evento: ‘+valor;
}
window.addEventListener(‘load’, iniciar, false);
Listado 16-8. Controlando la conexión.
Usamos funciones anónimas para responder a los eventos y enviar un valor que nos permita identificarlos luego en la función mostrar (). Este valor y el valor de la propiedad status son mostrados en la pantalla cada vez que el navegador realiza un nuevo paso en la generación del caché.
Hágalo usted mismo: Use los archivos HTML y CSS de ejemplos previos. Copie el código del Listado 16-8 dentro del archivo cache.js. Suba la aplicación a su servidor y vea cómo los diferentes pasos del proceso son mostrados en la pantalla de acuerdo al estado del caché cada vez que el documento es cargado.
IMPORTANTE: Si el caché ya fue creado, es importante seguir diferentes pasos para limpiar el viejo caché y cargar la nueva versión. Modificar el archivo manifiesto agregando un comentario es uno de los pasos necesarios, pero no el único. Los navegadores mantienen una copia de los archivos en el ordenador por algunas horas antes de siquiera considerar comprobar si existen actualizaciones, por lo que no importa cuántos comentarios o archivos agregue al manifiesto, el navegador utilizará el viejo caché por un tiempo. Para probar estos ejemplos, le recomendamos cambiar los nombres de cada archivo. Por ejemplo, agregar un número al final del nombre (como en cache2. j s) hará que el navegador considere ésta como una nueva aplicación y cree un nuevo caché. Esto, por supuesto, es solo útil por propósitos didácticos.
Progreso
Aplicaciones que incluyen imágenes, varios archivos de códigos, información para bases de datos, videos, o cualquier otro archivo de tamaño considerable pueden tomar un buen tiempo en ser descargadas. Para seguir este proceso, la API trabaja con el ya conocido evento progress. Este evento es el mismo que ya hemos estudiado en capítulos anteriores.
El evento progress solo es disparado mientras los archivos son descargados. En el siguiente ejemplo vamos a usar los eventos noupdate junto con cached y updateready analizados previamente para informar cuando el proceso es finalizado.
function iniciar(){
caj adatos=document.getElementById(‘caj adatos’);
cajadatos.innerHTML='<progress value=»0″ max=»100″>0%</progress>’;
cache=window.applicationCache;
cache.addEventListener(,progress’, progreso, false); cache.addEventListener(‘cached’, mostrar, false); cache.addEventListener(‘updateready’, mostrar, false); cache.addEventListener(‘noupdate’, mostrar, false);
}
function progreso(e){ if(e.lengthComputable){
var por=parseInt(e.loaded/e.total*100);
var barraprogreso=cajadatos.querySelector(«progress»);
barraprogreso.value=por;
barraprogreso.innerHTML=por+’%’;
}
}
function mostrar(){
caj adatos.innerHTML=’Terminado’ ;
}
window.addEventListener(‘load’, iniciar, false);
Listado 16-9. Progreso de la descarga.
Como siempre, el evento progress es disparado periódicamente para informar acerca del estado del proceso. En el código del Listado 16-9, cada vez que progress es disparado, la función progreso() es llamada y la situación es informada en pantalla usando un elemento <progress>.
Existen diferentes situaciones posibles al final del proceso. La aplicación podría haber sido almacenada en el caché por primera vez, en este caso el evento cached es disparado. También podría ser que el caché ya existe y una actualización se encuentra disponible, entonces cuando los archivos son finalmente descargados el evento que es disparado es updateready. Y una tercera posibilidad es que un caché ya estaba en uso y no se encontró ninguna actualización, en este caso el evento noupdate es el que será disparado. Escuchamos a cada uno de estos eventos y llamamos a la función mostrar () en cada caso para imprimir el mensaje «Terminado» en la pantalla, indicando de este modo la finalización del proceso.
Puede encontrar una explicación de la función progreso () en el Capítulo 13.
Hágalo usted mismo: Use los archivos HTML y CSS de ejemplos previos. Copie el código del Listado 16-8 dentro del archivo cache.js. Suba la aplicación a su servidor y cargue el documento principal. Deberá incluir un archivo de gran tamaño en el manifiesto para poder ver trabajando la barra de progreso (algunos navegadores establecen limitaciones sobre el tamaño del caché. Recomendamos probar este ejemplo con archivos de no más de 5 megabytes). Por ejemplo, usando el video trailer.ogg introducido en el Capítulo 5, el archivo manifiesto ser vería como el siguiente:
cache.html cache.css cache.j s trailer.ogg
# fecha 2011/06/27
IMPORTANTE: En nuestro ejemplo utilizamos innerHTML para agregar un nuevo elemento <progress> al documento. Esta no es una práctica recomendada pero es útil y conveniente por razones didácticas. Normalmente los elementos son agregados al documento usando el método Javascript createElement() junto con appendChild ().
Actualizando el caché
Hasta el momento hemos visto cómo crear un caché para nuestra aplicación, cómo informar al navegador cuando una actualización está disponible y cómo controlar el proceso cada vez que un usuario accede a la aplicación. Esto es útil pero no completamente transparente para el usuario. El caché y las actualizaciones del mismo son cargados tan pronto como el usuario ejecuta la aplicación, lo que puede producir demoras y mal funcionamiento. La API resuelve este problema incorporando nuevos métodos que nos permiten actualizar el caché mientras la aplicación está siendo utilizada:
update() Este método inicia una actualización del caché. Le indica al navegador que descargue primero el archivo manifiesto y luego continúe con el resto de los archivos si detecta algún cambio (los archivos para el caché fueron modificados). swapCache() Este método activa el caché más reciente luego de una actualización. No ejecuta ningún código y tampoco reemplaza recursos, solo le indica al navegador que un nuevo caché se encuentra disponible para su lectura.
Para actualizar el caché, lo único que necesitamos hacer es llamar al método update (). Los eventos updateready y noupdate serán útiles para conocer el resultado del proceso. En el próximo ejemplo, vamos a usar un nuevo documento HTML con dos botones para solicitar la actualización y comprobar cuál es el código que se encuentra actualmente en el caché.
<!DOCTYPE html>
<html lang=»es» manifest=»micache.manifest»> <head>
<title>Offline API</title>
<link rel=»stylesheet» href=»cache.css»> <script src=»cache.j s»></script>
</head>
<body>
<section id=»cajadatos»>
Aplicación para trabajar sin conexión </section>
<button id=»actualizar»>Actualizar Caché</button> <button id=»prueba»>Verificar</button>
</body>
</html>
Listado 16-10. Documento HTML para probar el método update () .
El código Javascript implementa técnicas ya estudiadas. Solo hemos agregado dos nuevas funciones para responder a los botones de la plantilla:
function iniciar(){
caj adatos=document.getElementById(‘caj adatos’);
var actualizar=document.getElementById(‘actualizar’); actualizar.addEventListener(‘click’, actualizarcache, false);
var prueba=document.getElementById(‘prueba’);
prueba.addEventListener(‘click’, probarcache, false);
cache=window.applicationCache;
cache.addEventListener(‘updateready’, function(){ mostrar(1); },
false);
cache.addEventListener(‘noupdate’, function(){ mostrar(2); },
false);
}
function actualizarcache(){ cache.update();
}
function probarcache(){
cajadatos.innerHTML+='<br>cambiar este mensaje’;
}
function mostrar(valor){ switch(valor){ case 1:
cajadatos.innerHTML+='<br>Actualización Lista’;
break;
case 2:
cajadatos.innerHTML+='<br>Actualización No Disponible’;
break;
}
}
window.addEventListener(‘load’, iniciar, false);
Listado 16-11. Actualizando el caché y comprobando la versión actual.
En la función iniciar (), se agregó una escucha para el evento click a los dos botones de la plantilla. Un clic en el botón actualizar llamará a la función actualizarcache() y ejecutará el método update(). Y un clic sobre el botón prueba llamará a la función probarcache() y un texto será mostrado en la cajadatos. Este texto nos facilitará la creación de una nueva versión del código con la que podremos comprobar si el caché es actualizado o no.
Hágalo usted mismo: Cree un nuevo documento HTML con el código del Listado 16-10. El manifiesto y el archivo CSS son los mismos de ejemplos previos (a menos que usted haya cambiado algunos nombre de archivos. En este caso deberá actualizar la lista de archivos dentro del manifiesto). Copie el código del Listado 1611 dentro de un archivo llamado cache.js, y suba todo a su servidor. Abra el documento principal en su navegador y use los botones para probar la aplicación.
Una vez que el documento HTML es cargado, la ventana muestra nuestra típica cajadatos y dos botones debajo. Como explicamos anteriormente, el botón «Actualizar Caché» tiene el evento click asociado con la función actualizarcache (). Si el botón es presionado, el método update () es ejecutado dentro de esta función y el proceso de actualización comienza. El navegador descarga el archivo manifiesto y lo compara con el mismo archivo que ya se encuentra en el caché. Si detecta que este archivo fue modificado, todos los archivos listados en su interior son descargados nuevamente. Cuando el proceso finaliza, el evento updateready es disparado. Este evento llama a la función mostrar () con el valor 1, correspondiente al mensaje «Actualización Lista». Por otro lado, si el archivo manifiesto no cambió, ninguna actualización es detectada y el evento noupdate es disparado. Este evento también llama a la función mostrar () pero con el valor 2, correspondiente al mensaje «Actualización No Disponible».
Puede comprobar cómo trabaja este código modificando o agregando comentarios al archivo manifiesto. Cada vez que presione el botón para actualizar el caché luego de una modificación, el mensaje «Actualización Lista» aparecerá en la cajadatos. Puede también hacer pruebas cambiando el texto en la función probarcache () para detectar cuándo una actualización está siendo utilizada como el caché actual.
IMPORTANTE: Esta vez no hay necesidad de eliminar el caché desde el panel de control del navegador para descargar una nueva versión. El método update() fuerza al navegador a descargar el archivo manifiesto y el resto de los archivos si una actualización es detectada. Sin embargo, el nuevo caché no estará disponible hasta que el usuario reinicie la aplicación.
API Offline es un grupo de técnicas que involucran un archivo especial llamado manifiesto y varios métodos, eventos y propiedades para crear un caché y poder ejecutar aplicaciones desde el ordenador del usuario. La API fue pensada para proveer acceso permanente a las aplicaciones y la posibilidad de trabajar mientras sin acceso a Internet.
Archivo manifiesto
El archivo manifiesto es un archivo de texto con la extensión .manifest conteniendo una lista de los archivos necesarios para construir el caché de la aplicación. Debe ser comenzado con la línea cache manifest y su contenido puede estar organizado bajo las siguientes categorías:
CACHE Esta categoría incluye los archivos que deben ser descargados para formar parte del caché.
NETWORK Esta categoría incluye los archivos que solo pueden ser accedidos cuando se está conectado.
FALLBACK Esta categoría permite definir archivos en el caché que serán usados en lugar de archivos en el servidor cuando éstos no estén disponibles.
Propiedades
El objeto Navigator incluye una nueva propiedad para informar el estado de la conexión:
onLine Esta propiedad retorna un valor booleano que indica la condición de la conexión. Es false (falso) si el navegador está desconectado y true (verdadero) en caso contrario.
La API provee la propiedad status para informar sobre el estado del caché de la aplicación. Esta propiedad es parte del objeto ApplicationCache y puede tomar los siguientes valores:
UNCACHED (valor 0) Este valor indica que ningún caché fue creado aún para la aplicación. IDLE (valor 1) Este valor indica que el caché de la aplicación es el más nuevo y no es obsoleto.
CHECKING (valor 2) Este valor indica que el navegador está buscando nuevas actualizaciones.
DOWNLOADING (valor 3) Este valor indica que los archivos para el caché están siendo descargados.
UPDATEREADY (valor 4) Este valor indica que el caché para la aplicación está disponible y no es obsoleto, pero no es el más nuevo; una actualización está lista para reemplazarlo.
OBSOLETE (valor 5) Este valor indica que el caché actual es obsoleto.
Eventos
Existen dos eventos para controlar el estado de la conexión:
online Este evento es disparado cuando el valor de la propiedad onLine cambia a true (verdadero).
offline Este evento es disparado cuando el valor de la propiedad onLine cambia a false (falso).
La API ofrece varios eventos, pertenecientes al objeto ApplicationCache, que informan acerca de la condición del caché:
checking Este evento es disparado cuando el navegador está comprobando si existen nuevas actualizaciones.
noupdate Este evento es disparado cuando no se encuentran nuevas actualizaciones. downloading Este evento es disparado cuando el navegador ha encontrado una nueva actualización y comienza a descargar los archivos. cached Este evento es disparado cuando el caché está listo para ser usado. updateready Este evento es disparado cuando la descarga de una nueva actualización ha finalizado.
obsolete Este evento es disparado cuando el archivo manifiesto no se encuentra disponible y el caché está siendo eliminado.
progress Este evento es disparado periódicamente durante el proceso de descarga de los archivos para el caché.
error Este evento es disparado si ocurre un error durante la creación o la actualización del caché.
Métodos
Dos métodos son incluidos en la API para solicitar una actualización del caché:
update() Este método inicia una actualización del caché. Indica al navegador que descargue el archivo manifiesto y el resto de los archivos si una actualización es detectada. swapCache() Este método activa el caché más reciente luego de una actualización. No ejecuta los nuevos códigos y tampoco reemplaza recursos, solo indica al navegador que un nuevo caché está disponible para su uso.