13

Tengo una insignia de "elementos nuevos" en una página que deseo actualizar de inmediato cuando la página se carga desde la memoria caché (es decir, al presionar "Atrás" o "Adelante" para volver a esta página). Cuál es la mejor manera de lograr esto?¿Mi página está cargada desde el caché del navegador?

La configuración es bastante simple. El diseño de la aplicación busca nuevos elementos cada 8 segundos y actualiza la insignia + lista de elementos en consecuencia.

$(function() { 
    setInterval(App.pollForNewItems, 8000); 
}); 

Cuando alguien navega fuera de esta página para mirar los detalles de un elemento, pueden pasar muchas cosas. Las cosas son "nuevas" hasta el cualquier usuario de las ha visto, y la aplicación probablemente tendrá varios usuarios usándola simultáneamente (el tipo de flujo de trabajo usado para un call center o tickets de soporte).

Para asegurarse de que las placas están siempre al día, que tengo:

$(window).bind('focus load', function (event) { 
    App.pollForNewItems(); 
}); 

..Y aunque esto funciona, la votación para los nuevos artículos en 'carga' sólo es útil cuando la página se carga desde el caché ¿Existe una manera confiable de navegador cruzado para saber si una página se está cargando desde el caché?

Respuesta

6

Una solución parcial hacky es tener una var con la hora actual establecida en el servidor, y establecer una var con la hora actual del cliente en la parte superior de la página. Si difieren en más de un cierto umbral (1 minuto?), Entonces podría suponer que es una carga de página en caché.

Ejemplo JS (utilizando la sintaxis de ASP.Net para el lado del servidor):

var serverTime = new Date('<%= DateTime.Now.ToUniversalTime().ToString() %>'); 
var pageStartTime = Date.UTC(new Date()); 
var isCached = serverTime < pageStartTime && 
       pageStartTime.getTime() - serverTime.getTime() > 60000; 

Por otra parte, el uso de cookies en el lado del cliente (asumiendo las cookies están habilitadas), se puede comprobar si hay una cookie con una clave única para la versión actual de la página. Si no existe ninguno, usted escribe una cookie para ello, y en cualquier otro acceso a la página, la existencia de la cookie le muestra que se está cargando desde el caché.

E.g. (supone que algunas funciones de cookie helper están disponibles)

var uniqueKey = '<%= SomeUniqueValueGenerator() %>'; 
var currentCookie = getCookie(uniqueKey); 
var isCached = currentCookie !== null; 
setCookie(uniqueKey); //cookies should be set to expire 
         //in some reasonable timeframe 
+1

no dependería del servidor y el cliente se sincronicen particularmente bien:/ – Matchu

+0

El problema con esto es que usted está asumiendo sincronización de relojes. El tiempo en JS está determinado por el tiempo de la computadora local, que puede diferir significativamente de la hora del servidor. – Yahel

+0

Buenos puntos, actualizaré para usar UTC. – jball

0

Personalmente, establecería el atributo de datos que contiene el ID del elemento para cada elemento.

I.e.

<ul> 
    <li data-item-id="123">Some item.</li> 
    <li data-item-id="122">Some other item.</li> 
    <li data-item-id="121">Another one..</li> 
</ul> 

Su función sería App.pollForNewItems agarrar el atributo data-item-id del primer elemento (si son más reciente primero) y lo envía al servidor con su solicitud original.

El servidor solo devolverá los elementos WHERE id > ... que luego puede anteponer a la lista.

Todavía estoy confundido de por qué quiere saber si el navegador tiene una versión en caché de la página.

Además, ¿hay algún motivo para vincular load en lugar de ready?

  • Cristiano
+0

Christian, buena sugerencia, aunque la aplicación ya hace exactamente lo que usted describe (aunque se comparan marcas de tiempo en lugar de ID). En cuanto a usar 'load' en lugar de 'ready', también quiero vincularme al evento 'focus', y quiero mantener mi código DRY. 'Listo' es un evento artificial construido por jQuery, y solo puede vincularse al documento. Si intenta '$ (document) .bind ('focus ready', {...})', el manejador nunca se disparará para el evento 'focus'. Dado que la diferencia de tiempo entre los eventos 'listo' y 'cargado' debe ser insignificante para las páginas cargadas desde el caché, 'cargar' está bien aquí. – Blackcoat

7

Usted puede pedir al navegador web para no almacenar en caché la página.Prueba estas cabeceras HTTP:

Particularmente, Cache-control: no-store es interesante porque indica al navegador que no almacene la página en memoria en todo lo que impide una página rancio que se carga cuando se pulse el botón de retroceso/avance.

Si lo hace, no tiene que sondear los datos de la carga de la página.

+0

¡Ni siquiera pensé en el almacenamiento en caché de los encabezados! Este es probablemente el enfoque correcto siempre y cuando el rendimiento no tenga éxito (me gustaría asegurarme de que no obligue al UA a descargar siempre los activos compartidos que deben almacenarse en caché en la aplicación, por ejemplo, JS, CSS, imágenes) Aunque esta es una solución para el problema, todavía tengo curiosidad acerca de si puede o no detectar si una página se carga desde el caché a través de JS. ¿Alguna idea? – Blackcoat

+0

No sé si hay una forma de saber si la página era del caché o no. @jball tiene la idea correcta para detectar la fecha en que se reescribió la página. – Jacob

+0

¿Dónde exactamente uno establece estas variables? – YakovL

10

Navigation Timing es en la mayoría de los navegadores de hoy (IE9 +) http://www.w3.org/TR/navigation-timing/#sec-navigation-info-interface

if (!!window.performance && window.performance.navigation.type === 2) { 
    // page has been hit using back or forward buttons 
} else { 
    // regular page hit 
} 
+0

esta solución parece no funcionar en Firefox? ¿Hay alguna solución para Firefox también? – Ralph

+0

¡la mejor respuesta para mi problema! – mgh

0

prueba siguiendo el script en su archivo js.

if(!!window.performance && window.performance.navigation.type == 2) 
{ 
    window.location.reload(); 
} 
Cuestiones relacionadas