13

J'ai un badge "nouveaux articles" sur une page que je veux mettre à jour immédiatement la page est chargée à partir du cache (c'est-à-dire lorsque vous appuyez sur "Retour" ou "Suivant" pour retourner à cette page). Quelle est la meilleure façon d'y parvenir?Ma page est-elle chargée à partir du cache du navigateur?

La configuration est assez simple. La mise en page de l'application recherche de nouveaux éléments toutes les 8 secondes et met à jour le badge + la liste des éléments en conséquence.

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

Lorsque quelqu'un quitte cette page pour regarder les détails d'un article, beaucoup de choses peuvent se produire. Les choses sont "nouvelles" jusqu'à ce qu'un utilisateur les ait vues, et l'application aura probablement plusieurs utilisateurs qui l'utilisent simultanément (le type de flux de travail utilisé pour un centre d'appels ou des tickets de support).

Pour vous assurer que les badges sont toujours à jour, j'ai:

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

..Et si cela fonctionne, le scrutin pour les nouveaux éléments sur la « charge » est utile uniquement si la page est chargée de le cache. Existe-t-il un moyen fiable de savoir si une page est chargée à partir du cache?

Répondre

6

Une solution hacky partielle est d'avoir un var avec l'heure actuelle définie sur le serveur, et définir un var avec l'heure actuelle du client en haut de la page. Si elles diffèrent de plus d'un certain seuil (1 minute?), Vous pouvez supposer qu'il s'agit d'un chargement de page en cache.

Exemple JS (en utilisant syntaxe ASP.Net pour le côté serveur):, vous pouvez vérifier un cookie avec une clé unique

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

Vous pouvez également utiliser des cookies sur le côté client (les cookies supposant sont activés) pour la version actuelle de la page. Si aucune n'existe, vous écrivez un cookie pour cela, et sur tout autre accès à la page, l'existence du cookie vous montre qu'il est chargé à partir du cache.

E.g. (suppose que certaines fonctions d'aide de cookie sont 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

Je ne dépend pas du serveur et le client à être synchronisés particulièrement bien:/ – Matchu

+0

Le problème avec cela est que vous êtes en supposant la synchronisation des horloges. L'heure dans JS est déterminée par l'heure de l'ordinateur local, qui peut différer considérablement de l'heure du serveur. – Yahel

+0

Bon point, je vais mettre à jour pour utiliser UTC. – jball

0

Personnellement, je définirais l'attribut de données contenant l'ID d'élément pour chaque élément.

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> 

Votre fonction App.pollForNewItems saisirait l'attribut data-item-id du premier élément (si le plus récent sont d'abord) et l'envoyer au serveur avec votre demande initiale.

Le serveur renverrait alors uniquement les éléments WHERE id > ... que vous pouvez ensuite ajouter à la liste.

Je suis toujours confus quant à la raison pour laquelle vous voulez savoir si le navigateur a une version en cache de la page.

De même, existe-t-il une raison de se lier à load au lieu de ready?

  • Christian
+0

Christian, bonne suggestion, bien que l'application fasse déjà exactement quoi vous décrivez (bien que les horodatages soient comparés à la place des ID). En ce qui concerne l'utilisation de 'load' au lieu de 'ready', je veux aussi me lier à l'événement 'focus', et je veux garder mon code DRY. 'Prêt' est un événement artificiel construit par jQuery, et il ne peut être lié qu'au document. Si vous essayez '$ (document) .bind ('focus ready', {...})', le gestionnaire ne sera jamais déclenché pour l'événement 'focus'. Puisque la différence de temps entre les événements 'ready' et 'load' devrait être négligeable pour les pages chargées depuis le cache, 'load' est très bien ici. – Blackcoat

7

Vous pouvez demander au navigateur de ne pas mettre en cache la page.Essayez ces en-têtes HTTP:

En particulier, Cache-control: no-store est intéressante car elle indique au navigateur de ne pas stocker la page en mémoire à tout ce qui empêche une page rassis étant chargée lorsque vous appuyez sur le dos/bouton vers l'avant.

Si vous faites cela à la place, vous n'avez pas à interroger les données sur le chargement de la page.

+0

Je ne pensais même pas à la mise en cache des en-têtes! C'est probablement la bonne approche tant que la performance ne prend pas un coup (je veux m'assurer que cela ne force pas l'UA à toujours télécharger les actifs partagés qui devraient être mis en cache dans l'application, par exemple JS, CSS, images). Bien que ce soit une solution au problème, je suis toujours curieux de savoir si vous pouvez ou non détecter si une page est chargée à partir du cache via JS. Des pensées? – Blackcoat

+0

Je ne sais pas s'il existe un moyen de savoir si la page provient du cache ou non. @jball a cependant la bonne idée de détecter la date à laquelle la page a été rendue. – Jacob

+0

Où exactement on met ces variables? – YakovL

10

Navigation Timing est dans la plupart des navigateurs maintenant (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

cette solution ne semble pas fonctionner dans Firefox? Existe-t-il une solution de contournement pour Firefox? – Ralph

+0

meilleure réponse pour mon problème !! – mgh

0

Essayez le script suivant dans votre fichier js.

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