Gibt es ein Ereignis IE Render Complete?

8

Beim Versuch herauszufinden, warum eine Seite 20s zum Laden benötigt, habe ich ein merkwürdiges Verhalten in IE8 festgestellt.

Das Szenario ist das.

Ich mache einen Ajax-Aufruf, es kehrt zurück und der Callback sah ungefähr so ​​aus

%Vor%

Dieses Codebeispiel dauerte jedoch 20 Sekunden.

Ich habe herumgespielt, Dinge getimt und Warnungen zwischen Methoden ausgegeben, und plötzlich waren es nur noch sechs Sekunden. Ich habe ein wenig mehr herumgespielt, um zu sehen, dass, wenn ich eine Verzögerung nach dem Aufruf von .html() einführte und bevor ich versuchte, das DOM zu manipulieren, die Seite VIEL schneller wurde. Es sieht jetzt so aus

%Vor%

Es dauert auch nur 6s, obwohl eine zusätzliche 1/10 Sekunde zum Prozess hinzugefügt wurde.

Meine Theorie ist, dass, weil das DOM nicht vollständig vom IE mit dem .html() -Aufruf auf den Bildschirm gerendert wurde, bevor versucht wird, damit zu arbeiten, eine Art Locking stattfindet.

Gibt es eine Möglichkeit zu bestimmen, wann der IE das Rendering von dem, was vom .html() zum DOM hinzugefügt wurde, fertig ist, so dass ich keinen willkürlichen Wert in einem setTimeout -Aufruf verwenden muss?

    
CaffGeek 04.08.2011, 16:05
quelle

5 Antworten

3

Sie können Ihrer Callback-Antwort ein einzelnes Pixelbild hinzufügen, dieses Image aus dem DOM nach .html (..) abrufen und an sein onload-Ereignis anhängen. Ich kann mir nicht vorstellen, dass das Onload-Ereignis des Bildes ausgelöst werden kann, bis der Browser es gerendert hat.

Stellen Sie sicher, dass das Bild im src eine eindeutige Kennung hat, damit es nicht zwischengespeichert wird ...

Seltsames Problem, das Sie haben - ich bin sicher, dass jemand eine elegantere Lösung anbieten wird:)

B

    
Brian 08.08.2011, 16:03
quelle
6

Sie sind mit Ihrer Analyse fast auf der Stelle. Lassen Sie mich versuchen zu erklären, warum setTimeout den Unterschied macht.

Wenn Sie sich diesen großartigen Artikel zum DOM-Rendering ansehen Sie werden verstehen, dass .html() zu einem Reflow führt.

Nun, mit den nächsten zwei Zeilen, was passiert ist, dass Sie den Rendering-Thread des Browsers binden. Browser können warten, bis die Ausführung des Skripts abgeschlossen ist, bevor ein Reflow-Vorgang durchgeführt wird (um mehrfache Reflow-Vorgänge zu vermeiden oder alle Änderungen zwischenzuspeichern).

Die Lösung - wir müssen dem Browser mitteilen, dass unsere html Änderungen vorgenommen wurden und Sie den Rendering-Prozess abschließen können. Die Art und Weise es zu tun - 1) beenden Sie Ihr Skript 2) Verwenden Sie setTimeout , um die Ausführung an den Browser zu liefern.

Das Ausführen einer setTimeout mit 0ms Verzögerung funktioniert auch, weil setTimeout grundsätzlich die Kontrolle über den Quellblock abgibt. Einer der Gründe, warum animationsbezogene Skripte so stark auf setTimeout und setInterval beruhen.

Eine weitere mögliche Verbesserung wäre die Verwendung von documentFragments , was John Resig hier

kurz erklärt

Ich denke, das Kombinieren dieser beiden sollte mehr Geschwindigkeit ergeben, aber natürlich keine Möglichkeit zu wissen, bis das Profiling fertig ist!

    
Mrchief 08.08.2011 21:04
quelle
2

Das Aufrufen von setTimeout verzögert die angegebene Funktion mindestens für die angegebene Zeit, aber sie wird nie ausgeführt, bevor die aktuelle Skriptausführung abgeschlossen ist. Das heißt, Sie könnten Ihr Timeout durch 0 Sekunden ersetzen.

Ein anderer Ansatz, den Sie vielleicht ausprobieren sollten, besteht darin, dass Sie auf eine Layouteigenschaft des generierten Inhalts zugreifen (z. B. Höhe von StoreDetailsContainer ). Auf diese Weise erzwingen Sie, dass der IE das Rendering beendet, bevor er die Kontrolle an Ihr Skript zurückgibt, da er nur den korrekten Wert bereitstellen kann, den Ihr Skript nach der Berechnung des Layouts angefordert hat.

Die dritte Möglichkeit, die Ihnen helfen könnte, ist, dass Sie sicherstellen, dass Sie den HTML-Code mit dem Seitenlayout analysieren. Dies würde verhindern, dass halb fertiggestellte Layouts immer wieder neu gezeichnet werden. Um dies zu tun, können Sie das Element StoreDetailsContainer vor dem Aufruf von html vom DOM trennen. Jetzt hat IE die Änderung, um das DOM zu konstruieren, ohne das Layout zu beeinflussen. Danach fügen Sie den StoreDetailsContainer erneut in das DOM ein. Im Vergleich zu einem normalen innerHTML -Satz ermöglicht dieses Trennen und erneute Anhängen des Containers, dass Sie steuern, wann der HTML-Code analysiert wird, um den DOM-Baum zu erstellen, und wann das Layout berechnet wird.

    
Augustus Kling 08.08.2011 19:35
quelle
0

Probieren Sie diesen Code aus. Das load-Ereignis wird nach dem ready-Ereignis ausgelöst, sodass es funktioniert.

%Vor%     
Slawomir Pasko 11.08.2011 22:58
quelle
0

Ich denke, dass es so funktionieren könnte:

%Vor%     
David L. 03.01.2016 10:22
quelle