Hallo,
ich möchte eine Art "Fortschrittsbalken" erstellen, um dem User zu zeigen, wie lange das Script noch braucht bis er "fertig" mit dem Erstellen bestimmter Listen ist.
Wie lange läuft das Script und warum braucht es so lange? Sind das etwa synchrone Input/Output-Operationen?
Also nach jedem Aufruf der o.g. Funktionen den Prozentwert um 5 erhöhen und gleichzeitig ausgeben. Und genau da zeigt er es nicht an.
Das Script läuft alle Funktionen durch ohne das Design zu verändern. Erst am Ende wird es ausgegeben bzw. ist die Veränderung sichtbar, aber nur der letzte Wert.
Ja, das ist normal. Der Browser setzt eine Änderung am DOM erst durch Layouting und Painting um, wenn der aktuelle Call-Stack abgearbeitet ist und der JavaScript-Interpreter zur Ruhe kommt bzw. mit dem nächsten geplanten Funktionaufruf weitermacht. Stichwort »JavaScript Event Loop«. Sprich: Dein JavaScript muss zur Ruhe kommen.
Wie also bewerkstellige ich es, dass er mir eine Art "Ladezustand" übermittelt? Oder anders gefragt: Wie halte ich das Script kurz an, damit er die "Veränderung" anzeigt? Mittels setTimeout() oder gibt es da andere Möglichkeiten dazu?
Ja, setTimeout bzw. setImmediate ist eine Möglichkeit. Eine andere ist das Erzwingen des Renderings durch die Abfrage von offsetWidth oder einer anderen Eigenschaft, dessen Wert der Browser erst durch Layouting korrekt zurückliefern kann.
PS: ich will nicht auf die Eingabe des Users warten (war schonmal ein Thema von mir), sondern das Ändern des Design's nach jeder Funktion.
Das Problem ist letztlich dasselbe wie bisher. :) Wenn du zwischen JavaScript-Operationen etwas ausgeben willst, muss du dein JavaScript in kleine Teile aufsplitten, die asynchron aufgerufen werden können, sodass der aktuelle Call-Stack abgearbeitet wird, damit der Browser den Zwischenstand rendert.
Das lässt sich z.B. mithilfe einer Queue lösen, die abgearbeitet wird:
var one = function () {…};
var two = function () {…};
var three = function () {…};
var renderStatus = function () {…};
var queue = [one, two, three];
var loop = function () {
var func = queue.shift();
if (func) {
func(); // Führe Schritt aus
renderStatus(); // Erstatte Bericht
setTimeout(loop, 1); // Beende Call-Stack, erzeuge neuen
// Jetzt kann der Browser rendern
}
};
loop();
Mathias