JS zur Laufzeit einer Funktion anzeigen

Tommy57

Erfahrenes Mitglied
Hallo,

ich habe ein einfaches Programm in JavaScript geschrieben, dass mir Tabellen nach dem BubbleSort Prinzip sortiert. Bei sehr umfangreichen Tabellen, dauert dies schon mal 1-2 Sekunden.

An dieser Stelle würde ich gerne wollen, dass dem User sortierte Zeilen direkt angezeigt werden und nicht erst, wenn das Skipt komplett durchgelaufen ist. Das macht auch in sofern Sinn, da der User sowieso nicht alle Zeilen auf einmal sehen kann, sondern lediglich nur die ersten 20, wenn es hoch kommt.

Die Sortierung selbst findet in einer For-Schleife statt. Weiß jemand, wie ich zwischendurch, die View quasi schon mal rendern lassen könnte, damit der User gleich nach Knopfdruck schon ein Resultat zu sehen bekommt?

Gruß
 
Vielleicht solltest du deine Sortierung ändern. Greifst du während des Sortierens auf die Tabelle zu (DOM) oder machst du alles z.B. in einem Array?

Vielleicht kannst du uns ja Beispiel HTML + JavaScript zeigen.
 
Hi CPoly,

ich sortiere direkt über die Elemente durch, also nicht über ein Array. Der Code ist recht lang und auch uninteressant, finde ich. Das sind einfach zwei ineinander verschachtelte for-schleifen, wo die äußere, die Zeile representiert, die mit allen von der inneren verglichen wird.

Der Grund, warum ich genau diesen Lösungsansatz gewählt hatte:
ich bin anfangs der Meinung gewesen, dass das JS sortierte Zeilen direkt anzeigt, und im Hintergrund dann weiter sortiert. Für den User wäre dies optimal, weil er so die gewünschte Sortierung sofort sehen würde.

Nur leider zeigt JS keine Zwischenstände an. Gibt es die Möglichkeit, dass irgendwie zu erzwingen?

Gruß
 
Wenn du willst, dass deine Benutzer das sehen und ewig warten müssen, dann bau für jede Vertauschung eine Verzögerung ein. Da es kein sleep in JavaScript gibt, müsstest du deinen Code etwas um strukturieren.
Wenn du wirklich direkt die Elemente umsortierst (also tatsächlich für jede Vertauschung das Element im Baum umhängst), ist das kein Wunder, dass das so lange dauert, denn das erzwingt im Browser in reflow und normalerweise auch ein repaint, aber da du das ja nicht nur einmal machst, kommt das repaint erst, wenn die ganze Arbeit zu ende ist.

Ich würde beim Sortieren so vorgehen:

Ich würde direkt vorm Sortieren alle tr-Elemente aus dem Dokument aushängen, das Array sortieren und dann wieder einhängen.

Ich werde das mal schnell implementieren...

...30 Minuten später: Jetzt hatte ich auch meine tägliche Dosis JavaScript :-D

Dauert auch mit 10.000 Zeilen nur etwa 7 Sekunden. Aber das wären schon viele Zeilen :-D.

HTML:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
	<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
	
	<title>Table sort</title>
</head>

<body>
	<div>
		<table border="1">
			<thead>
				<tr>
					<th onclick="sort(0, 'number');">ID</th>
					<th onclick="sort(1, 'string');">Name</th>
					<th onclick="sort(2, 'number');">Note</th>
				</tr>
			</thead>
			<tbody>
				<tr><td>0</td><td>FFjQv</td><td>2.0607070818472843</td></tr>
				<tr><td>1</td><td>pdrqz</td><td>1.358964791365755</td></tr>
				<tr><td>2</td><td>ULEOMPfd</td><td>1.5352823128502222</td></tr>
				<tr><td>3</td><td>ASKBGsXIzdnnOs</td><td>0.4362844667745236</td></tr>
				<tr><td>4</td><td>NQUtzYzdsym</td><td>3.5845737662972676</td></tr>
				<tr><td>5</td><td>oqCRAnwBgjIj</td><td>3.1046372969410627</td></tr>
				<tr><td>6</td><td>DGlysBABoPDi</td><td>0.37464240397625703</td></tr>
				<tr><td>7</td><td>LIDfBkOdeCLi</td><td>1.932516225232793</td></tr>
				<tr><td>8</td><td>JzoXrzzwigQt</td><td>1.576257621734308</td></tr>
				<tr><td>9</td><td>DgXstLdX</td><td>2.043269863916968</td></tr>
			</tbody>
		</table>
	</div>
	
	<script type="text/javascript">
	/* <![CDATA[ */
	var
		table = document.getElementsByTagName('table')[0],
		tableBody = table.getElementsByTagName('tbody')[0];
		rows = tableBody.getElementsByTagName('tr');

	function sort(col, dataType) {
		var arr = Array.prototype.slice.call(rows);
	
		//Tabellen leeren
		tableBody.innerHTML = '';
	
		arr.sort(function(row1, row2) {
			//Die zu vergleichenden Spalten
			var
				data1 = row1.getElementsByTagName('td')[col]
				data2 = row2.getElementsByTagName('td')[col];
		
			//Inhalte der Spalten
			data1 = (data1.innerText || data1.textContent);
			data2 = (data2.innerText || data2.textContent);
		
			//Falls wir Zahlen anstelle von Strings vergleichen wollen
			if(dataType === 'number') {
				data1 = parseFloat(data1);
				data2 = parseFloat(data2);
			
				return data1 - data2;
			}
		
			if(data1 > data2) {
				return 1;
			}
		
			if(data1 < data2) {
				return -1;
			}
		
			return 0;
		});
	
		//Tabelle wieder befüllen
		for(var i = 0; i < arr.length; i++) {
			tableBody.appendChild(arr[i]);
		}
	}
	/* ]]> */
	</script>
</body>

</html>
 
Okay, hab mir das mal angeschaut. Also bei meinem Sortierverfahren braucht man für etwa 1.500 Zeilen schon 9 Sekunden.

Ich springe halt durchgehend im DOM hin und her, also arbeite komplett ohne Array.

Gibt es an meiner Sortiervariante was auszusetzen?

Gibt es eine Möglichkeit, ein Repaint zu erzwingen?

Gruß
 
Du müsstest dann deine Sortierung etwas umbauen. Und zwar kann dein Bubblesort zwar iterativ bleiben, aber du darfst nicht alles auf einmal machen. Z.B. könntest du alle 100 rows eine kurze Unterbrechung machen. Dafür müsstest du die Sortierung in eine Funktion auslagern, der du als Parameter die Schleifenzähler übergeben kannst. Beim Bubblesort würde sich auch anbieten einfach nach jedem Durchlauf einmal kurz zu pausieren. Also lass die ganz äußere while Schleife weg Etwa so (ungetestet)

Javascript:
function sort() {
    var swapped = false;

    for(var i = 1; i < list.len; i++) {
        if(list[i - 1] > list[i]) {
              //Vertauschung
              //...

              swapped = true;
        }
    }

    if(swapped) {
        //Dadurch sollte ein repaint erzwungen werden
        window.setTimeout('sort()', 0);
    }
}
 
Super, das klappt!

Ich muss das aber in naher Zukunft trotzdem komplett alles umbauen. Deine Variante ist 10 mal schneller als meine. Nur weil meine so langsam ist, muss ich zu solchen blöden mitteln greifen:(
 

Neue Beiträge

Zurück