2010-02-04 10 views
7

Ich habe einen lang laufenden Bericht und möchte dem Benutzer während des Generierens ein Warte-Spinner anzeigen. Ich habe diese Arbeit bereits gemacht, bin mir aber nicht sicher, ob ich es am besten oder richtig mache.Wann beginnen Browser teilweise übertragenes HTML zu rendern?

Dies ist mit ColdFusion, aber es könnte jede Sprache ich denke. Oben auf der Seite habe ich Javascript (jQuery), das einen Warte-Spinner zeigt, und es gibt einen documentReady-Handler, in dem ich den Spinner abnehme. Ich flush die Ausgabe (wenn es darauf ankommt) und dann der Rest des Codes funktioniert auf den Inhalt des Berichts. Dies brachte den Spinner nicht zum Laufen, und ich stellte mir vor, dass, obwohl ich Dinge auf dem Server löschte, auf dem Weg etwas gepuffert wurde und der Browser den Spinner-Code nie zu spät sah. Also fügte ich eine Schleife hinzu, bevor ich einige hundert Zeilen HTML-Kommentare ausspuckte. Nach der Feinabstimmung der Anzahl der Zeilen war das der Fall. Ich nahm an, dass dies auch von anderen Seiten gemacht wurde.

Aber: Während ich heute eine andere Seite von mir beobachte, die den Zeilen-Status eines lang laufenden Jobs ausspuckt, fällt mir auf, dass diese Seite nach jeder Zeile geleert wird und der Browser diese schrittweise nach Wunsch rendert. Dies entspricht nicht meiner Schlussfolgerung von oben und jetzt weiß ich nicht, was die Regeln sind. Gibt es einen vorhersehbaren Weg, dies zu tun? Variiert das pro Browser?

CLARIFICATION: Ich schätze die Antworten, die versuchen, den richtigen Weg zu einer Wartezeit zu erklären, aber ich benutze nur ein Warten-Spinner als Beispiel, um meine eigentliche Frage zu illustrieren: gibt es zuverlässige Möglichkeiten, um zu prognostizieren, wenn Browser wird anfangen, HTML zu rendern, wenn es über das Internet gestreamt wird? Es ist offensichtlich, dass Browser nicht darauf warten, dass das/html-Tag beginnt, zu arbeiten. Diese Frage hat nicht unbedingt etwas mit Javascript zu tun. Die zweite Seite, die ich beschreibe, ist reiner HTML-Code.

+0

Wenn ich Sie richtig verstehe, laden Sie einen Spinner mit jQuery in das DOM, bevor das Dokument bereit Ereignis ausgelöst hat? Ich weiß nicht, ob das mit deinem Problem zu tun hat, aber das ist nicht das, was du machen willst. Und ist das ein Ajax-Anruf, den Sie machen? Es klingt, dass Sie versuchen, AJAX-ähnliche Funktionen auszuführen (laden Sie das DOM mit einem wartenden Indikator, machen Sie einen AJAX-Aufruf, um den Bericht zu laden, ersetzen Sie den wartenden Indikator durch einen Bericht, aber ohne AJAX zu verwenden). –

+0

Es gibt keinen AJAX-Anruf. Es gibt einfache Inline-jQuery, um den Spinner anzuzeigen. Der Rest der Seite sind die tatsächlichen Berichtsdaten. Das funktioniert gut. Warum möchte ich das nicht tun? Wenn ich es zum Laufen bringen kann, scheint es viel einfacher zu sein, die Seite in zwei Teile zu zerlegen - das Anfangsbit plus den Bericht, der über AJAX zurückgegeben wurde. – DaveBurns

Antwort

1

--- Nachklärung Antwort ---

Meine ursprüngliche Antwort sollte jemand nützlich sein (hoffe ich), aber es ist nicht eine direkte Antwort auf die Frage, also werde ich einen anderen Posten Antwort

Die Antwort auf Ihre neu gestellte Frage ist "Nein". Im Falle von FF gibt es eine vordefinierte anfängliche Render-Verzögerung, aber andere Browser werden anders sein. Diese FF Render-Verzögerung kann ebenfalls optimiert werden.

Mit FF als Beispiel, diese anfänglichen 250ms sind Zeit für FF, um herauszufinden, mindestens einige nützliche Informationen vor dem ersten Render zu versuchen. Es macht dann zusätzliche Renderings periodisch, während es mehr lernt.

Sie können nicht feststellen, wann der Browser mit dem Rendern des HTML-Dokuments begonnen hat.

--- Original Antwort ---

direkt Um Ihre Frage zu beantworten, ich glaube, Firefox 250ms wartet, bevor es auf den ersten Daten handeln empfangen, aber das kann geändert werden. Für andere Browser, weiß ich nicht.

Allerdings möchten Sie diese Route nicht gehen.

Wenn jQuery bereit ist, seine Magie zu arbeiten, wird es Sie wissen lassen, indem Sie $(document).ready() feuern. Bis dahin wird jeder Versuch, jQuery zu verwenden, fehlschlagen. Mit anderen Worten, Ihr Spinner wird nicht angezeigt, da jQuery noch nicht bereit ist, diese Anfrage zu verarbeiten.

Betrachten Sie das folgende Beispiel, in dem zwei Platzhalter auf dem Bildschirm angezeigt werden, und wir verwenden jQuery, um sie auszublenden.

<html> 
    <head> 
     <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.1/jquery.min.js"></script> 
     <script> 

      // We're not ready yet. This will fail. 
      $(".placeholder").hide(); 

      $(document).ready(function(){ 
       // This won't fail 
       $("#one").hide(); 
      }); 

     </script> 
    </head> 
    <body> 
     <div id="one" class="placeholder">Placeholder One</div> 
     <div id="two" class="placeholder">Placeholder Two</div> 
    </body> 
</html> 

Es befindet sich auf den ersten Blick erscheint, dass $("#one").hide(); redundant ist, aber das ist nicht wahr. $(".placeholder").hide(); wird aufgerufen, bevor jQuery bereit ist, also hat es keine Wirkung. Daher wird "Placeholder Two" angezeigt (und nicht "Placeholder One"), wenn Sie das Markup oben in einem Webbrowser ausführen.

Jetzt, wo wir das aus dem Weg haben, ist die Lösung für das größere Problem (der "richtige Weg") AJAX.

  1. Laden Sie eine Basisseite, die den Spinner-Code enthält. Stellen Sie sicher, dass der Code zum Laden des Spinner als Teil von $(document).ready() ausgeführt wird.
  2. Verwenden Sie jQuery's AJAX functionality, um den gewünschten Bericht zu erhalten.
  3. Wenn es zurückkommt, verstecken Sie den Spinner, injizieren Sie den Bericht in Ihre Basisseite.

Viel Glück!

+0

E-man - Woher hast du die 250ms-Nummer? Du bist die zweite Person, die sagt, dass das, was ich mache, nicht das ist, was ich tun möchte. OK, aber warum? Ist es unzuverlässig? Dies ist eine Inhouse-App, bei der die Verwendung von FF erforderlich ist, so dass ich mir keine Sorgen über andere Browser mache (aber das möchte ich auch wissen). Ich kenne den AJAX-Ansatz, versuchte aber, die zusätzliche Komplexität zu vermeiden. Über Ihr Beispiel - Ich denke, Sie sagen, dass die ursprüngliche hide() nicht funktioniert, weil jQuery nicht bereit ist, aber mein aktueller Code funktioniert und dies durch den Aufruf von jQuery vor document.ready ausgelöst wird. Fehle ich etwas? – DaveBurns

+0

Für die 250ms http://hackaday.com/2004/12/26/speed-up-firefox/ Sie können jQuery nicht verwenden bevor $ (document) .ready() feuert-- Ich denke, Ihre Kommentar-Schleife ist erzwingt eine "ok etwas ist blockiert, lass uns nehmen, was wir für jetzt haben" Situation in FF (best rate). Es ist nicht normal, da bin ich mir sicher. Ich werde die neu gestellte Frage in einer anderen Antwort beantworten. –

+1

Das ist einfach falsch, dass Sie jQuery nicht verwenden können, bevor '.ready()' aufgerufen wird. Sie können nicht garantieren, dass jedes Element im Dokument verfügbar ist, wenn Sie Aufrufe vor '.ready() 'auslösen, aber viele Elemente können vorhanden sein. Insbesondere wenn Sie ein Skript-Tag in Ihren HTML-Body einfügen, können alle Elemente vor dem Script-Tag sicher verwendet werden, obwohl '.ready()' noch nicht ausgelöst wurde. – jfriend00

0

Ich erwarte, dass es je nach Browser variieren wird: einige beginnen zu rendern, bevor die Seite vollständig empfangen wurde; Andere warten vor dem Start auf die gesamte HTML-Datei.

Ich stelle fest, dass die HTTP-Antwort-Spezifikation einen "206 Partial Content" -Header bietet, der einige Hoffnung für eine browserübergreifende Lösung bieten könnte, die es wert ist, untersucht zu werden.

Es gibt fast sicher eine Reihe von Möglichkeiten, um es zu schneiden, aber meine unmittelbare Idee wäre, die Stub-Seite zu liefern, dann Ajax verwenden, um die Fragmente bei Bedarf zu ziehen und zu rendern. Beispielsweise scheinen viele große Websites zunächst eine minimale Ansicht zu liefern, und wenn Sie ausreichend nach unten scrollen, wird eine Ajax-Anforderung ausgelöst, um mehr Daten abzurufen und an die Seite anzuhängen. zB: facebook, slashdot.

Ich kann mir nicht vorstellen, dass dies zu schwer zu implementieren ist; sogar mit Coldfusion. Sie starten den Kreisel, wenn Sie die Ajax-Anforderung auslösen und stoppen, wenn der Rückruf aufgerufen wird.

+0

Für die Nachwelt: Die Spekulation über '206 Partial Content' ist ungenau. Dieser Antwortcode darf nur verwendet werden, um auf HTTP-Bereichsanforderungen zu antworten - das heißt, eine Anforderung für einen Teil einer Ressource, z. B. das Suchen in einem Audio-/Videostream oder das erneute Laden eines Downloads. – duskwuff

2

Wenn ich Sie richtig verstehe, möchten Sie, dass ein "loading" -Bild angezeigt wird, während die Seite noch Inhalte lädt.

Was ich tue, und was ich glaube, ist der beste Weg, ein Div-Tag oben auf Ihrer Seite, am nächsten zu Body-Tag, das das Laden Bild/Text enthält, hinzuzufügen. Sie können dieses div mit Hilfe von etwas css woanders platzieren.

Dann Jquery entfernen dieses Div, wenn die Seite geladen wird. Anstatt $ (Dokument) .ready zu verwenden, wie einige empfohlen haben, würde ich stattdessen $ (Fenster) .load verwenden, da es aktiviert wird, wenn die komplette Seite vollständig geladen ist, einschließlich aller Rahmen, Objekte und Bilder.
Se Link hier; http://4loc.wordpress.com/2009/04/28/documentready-vs-windowload/

Beispiel;

<body>  
<div id="loading" style="z-index:200; width:100%; height:40px; border-top:2px #D4D4D4 solid; background:#E8E8E8; color:#000; position:fixed; bottom:0; left:0;"> 
    <div align="center"> 
     <img src="load.gif" alt="Loading..."> 
    </div> 
</div> 
<script type="text/javascript"> 
    $(window).load(function() { $("#loading").remove(); }); 
</script> 
[...] 

...

1

Andere als die in der Verzögerung für Firefox gebaut, gibt es andere Bereiche, die den Browser warten vor dem Rendern verursachen.

Da eine HTML-Seite an den Browser gesendet wird, muss sie zuerst entscheiden, wohin die Dinge gehen, bevor sie den Bildschirm zeichnen kann. Zum Beispiel sind Tabellen berüchtigt dafür, Rendering-Verzögerungen zu verursachen. Um eine Tabelle zu zeichnen, muss der Browser Spaltengrößen berechnen. Wenn Sie Prozentangaben als Spaltenbreite verwenden oder gar nicht angeben, muss der Browser vor dem Rendern die gesamte Tabelle abrufen.

Wenn Sie jedoch etwas wie das css-Attribut verwenden, kann der Browser einfach die erste Zeile lesen und mit dem Zeichnen beginnen, während Daten an ihn übergeben werden.

Andere Tags können ähnliche Probleme verursachen. Grundsätzlich muss der Browser immer den gesamten zu rendernden Inhalt haben, wenn der Browser die Größe des Inhalts berechnen muss. Wenn Sie durch die Verwendung von Elementen mit fester Größe (Breite/Höhe) im Voraus Tipps geben können, muss der Browser nichts herausfinden und kann die Elemente so zeichnen, wie sie heruntergeladen werden.

Als eine selbst auferlegte Regel lasse ich den Browser nie etwas feststellen. Stattdessen gebe ich meinen Elementen feste Größen. Als Ergebnis haben die Websites, an denen ich arbeite, normalerweise ein blitzschnelles Rendering.