13

Ich habe ein Abzeichen "neue Gegenstände" auf einer Seite, die ich sofort aktualisieren möchte die Seite aus dem Cache geladen wird (d. H. Wenn Sie "Zurück" oder "Weiter" drücken, um zu dieser Seite zurückzukehren). Was ist der beste Weg, dies zu erreichen?Wird meine Seite aus dem Browser-Cache geladen?

Das Setup ist ziemlich einfach. Das Layout für die App sucht alle 8 Sekunden nach neuen Objekten und aktualisiert die Badge + Liste der Elemente entsprechend.

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

Wenn jemand von dieser Seite weg navigiert, um sich die Details eines Objekts anzusehen, kann viel passieren. Die Dinge sind "neu", bis alle Benutzer hat sie angezeigt, und die App wird wahrscheinlich mehrere Benutzer haben es gleichzeitig (die Art von Workflow für ein Call-Center oder Support-Tickets verwendet).

Um sicherzustellen, dass die Abzeichen sind immer auf dem neuesten Stand, die ich habe:

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

..und obwohl dies funktioniert, Polling für neue Elemente auf ‚Last‘ ist nur dann sinnvoll, wenn die Seite geladen wird von der Cache. Gibt es eine zuverlässige Cross-Browser-Möglichkeit, um festzustellen, ob eine Seite aus dem Cache geladen wird?

Antwort

6

Eine teilweise Hacky-Lösung ist eine Var mit der aktuellen Zeit auf dem Server festgelegt, und legen Sie eine Variable mit der aktuellen Client-Zeit am Anfang der Seite. Wenn sie sich um mehr als einen bestimmten Schwellenwert (1 Minute?) Unterscheiden, können Sie davon ausgehen, dass es sich um eine zwischengespeicherte Seitenladung handelt.

Beispiel JS (unter Verwendung von ASP.Net Syntax für die Serverseite):

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

Alternativ Cookies auf der Client-Seite (unter der Annahme von Cookies aktiviert ist) verwenden, können Sie mit einem eindeutigen Schlüssel für einen Cookie überprüfen für die aktuelle Version der Seite. Wenn keine vorhanden ist, schreiben Sie ein Cookie dafür, und bei jedem anderen Seitenzugriff zeigt das Vorhandensein des Cookies an, dass es aus dem Cache geladen wird.

z. (Angenommen, einige Cookie-Hilfsfunktionen sind verfügbar)

+1

Ich würde nicht auf dem Server und Client hängen besonders gut synchronisiert werden:/ – Matchu

+0

Das Problem dabei ist, dass Sie die Synchronisierung von Uhren gehen davon aus. Die Zeit in JS wird von der Zeit des lokalen Computers bestimmt, die sich erheblich von der Serverzeit unterscheiden kann. – Yahel

+0

Gute Punkte, ich werde aktualisieren, um UTC zu verwenden. – jball

0

Persönlich würde ich Datenattribute festlegen, die die Element-ID für jedes Element enthalten.

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> 

Ihre App.pollForNewItems Funktion würde das data-item-id Attribut des ersten Elements greifen (wenn neueste zuerst ist) und sie an den Server mit Ihrer ursprünglichen Anfrage senden.

Der Server würde dann nur die Elemente WHERE id > ... zurückgeben, die Sie dann der Liste voranstellen können.

Ich bin immer noch verwirrt, warum Sie wissen möchten, ob der Browser eine zwischengespeicherte Version der Seite hat.

Gibt es auch einen Grund für die Bindung an load statt ready?

  • Christian
+0

Christian, guter Vorschlag, obwohl die Anwendung bereits genau das tut Sie beschreiben (obwohl Zeitstempel verglichen mit IDs verglichen werden). Was die Verwendung von 'Laden' anstelle von 'Bereit' betrifft, möchte ich auch an das 'Fokus' -Ereignis binden, und ich möchte meinen Code DRY behalten. 'Bereit' ist ein künstliches Ereignis, das von jQuery erstellt wurde und nur an das Dokument gebunden werden kann. Wenn Sie '$ (document) .bind ('focus ready', {...}) 'versuchen, wird der Handler nie für das Ereignis' focus 'ausgelöst. Da der Zeitunterschied zwischen den Ereignissen 'ready' und 'load' für Seiten, die aus dem Cache geladen werden, vernachlässigbar sein sollte, ist 'load' hier in Ordnung. – Blackcoat

7

können Sie den Web-Browser bitten, die Seite nicht zwischenspeichern.Versuchen Sie, diese HTTP-Header:

Insbesondere Cache-control: no-store interessant ist, weil es den Browser anweist, die Seite nicht im Speicher speichern überhaupt, die eine veraltete Seite verhindert geladen, wenn Sie die Vor/Zurück-Button drücken.

Wenn Sie dies stattdessen tun, müssen Sie beim Laden der Seite keine Daten abrufen.

+0

Ich habe nicht einmal darüber nachgedacht, Header zu cachen! Dies ist wahrscheinlich der richtige Ansatz, solange die Leistung nicht beeinträchtigt wird (ich möchte sicherstellen, dass der UA nicht immer freigegebene Assets herunterlädt, die in der App zwischengespeichert werden sollten, z. B. JS, CSS, Bilder). Obwohl dies eine Lösung für das Problem ist, bin ich immer noch neugierig darauf, ob Sie erkennen können, ob eine Seite über JS aus dem Cache geladen wurde oder nicht. Irgendwelche Gedanken? – Blackcoat

+0

Ich weiß nicht, ob es eine Möglichkeit gibt zu sagen, ob die Seite aus dem Cache stammt oder nicht. @jball hat die richtige Idee, um das Datum zu bestimmen, an dem die Seite gerendert wurde. – Jacob

+0

Wo genau setzt man diese Variablen? – YakovL

10

Navigation Timing in den meisten Browsern ist jetzt (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

diese Lösung scheint nicht in Firefox zu funktionieren? Gibt es einen Workaround für Firefox? – Ralph

+0

beste Antwort für mein Problem !! – mgh

0

versuchen Sie folgendes Skript in Ihrer js-Datei.

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