Bildschirmausgabe während Schleifendurchlauf

Status
Dieses Thema wurde gelöst! Zur Lösung gehen…

Sprint

Erfahrenes Mitglied
Hallo zusammen,

ich bin gerade dabei, ein Script für einen Statistikfreak zu schreiben. Dabei kann es vorkommen, daß das Script auch mal mehrere Minuten läuft. Daher wäre es schön, daß sich während des Schleifendurchlaufs am Bildschirm irgendwas tut. Nur werden hier alle Daten erst ausgegeben, wenn schon alles passiert ist.
Javascript:
function getLand(){
    var land = $('#land').val();
    var rueckgabe = '';
    $.ajax({
        type: "POST",
        url: "_pzkunden.php",
        async: false,
        data: {land: land},
        success: function(data){
            rueckgabe = JSON.parse(data);
        }
    });
    $('#gesAnzahl').html('insgesamt zu verarbeiten: '+rueckgabe.length);
    $.each( rueckgabe, function( key, val ) {
        if (val == 'stop')
            alert('fertig');
//            getcsv();
        else
            getDaten(val);
    });
}

function getDaten(kdnr){
    $.ajax({
        type: "POST",
        url: "_pzzaehler.php",
        async: false,
        data: {kdnr: kdnr},
        success: function(data){
            if (data == 'ok')
                $('#kdnrAusgabe').html('aktuelle KdNr: '+kdnr);
            else
                alert('Fehler bei Kdnr '+kdnr);
        }
    });
}

Gibt es da eine Möglichkeit, die Ausgabe auch während des Laufs sichtbar zu machen? Ob es dann lesbar ist oder nicht, ist egal. Hauptsache, es rührt sich was.
 

Sempervivum

Erfahrenes Mitglied
PS: Ich habe da etwas bei mir ausgegraben:
Code:
    <style>
        #cprogress {
            width: 200px;
            height: 20px;
            border: 2px solid black;

        }
        #progressbar {
            height: 100%;
            width: 0;
            background-color: blue;
        }
    </style>
    <div id="cprogress"><div id="progressbar"></div></div>
    <div id="content"><img src="images/loader.gif" /></div>
    <script>
        var progress = 0.1;
        var url = "testdownload.json";

        var oReq = new XMLHttpRequest();

        //Download progress
        oReq.addEventListener("progress", function (evt) {
            if (evt.lengthComputable) {
                var percentComplete = evt.loaded / evt.total;
                //Do something with download progress
                console.log(evt.total);
                if (percentComplete > progress) {
                    console.log("Finished " + progress * 100 + "%.");
                    progress += 0.1;
                    progressbar.style.width = percentComplete * 100 + "%";
                }
            }
        }, false);
        oReq.addEventListener('load', function (event) {
            if (oReq.status >= 200 && oReq.status < 300) {
                console.log(oReq.responseText);
                content.innerHTML = oReq.responseText;
            }
        });

        oReq.open("get", url, true);
        oReq.send();
    </script>
 

Sprint

Erfahrenes Mitglied
Allerdings stellt sich die Frage, warum das Ganze so lange dauert. Möglicher Weise gibt es noch Optimierungspotenzial auf Serverseite?
Das Problem dabei ist, daß tausende von Datensätzen durchsucht und gezählt werden müssen. Und auch wenn die Zählung selbst nur Sekundenbruchteile braucht, addiert sich das bei Tausenden von Zählungen auf ganz schöne Werte.

Gibt es denn einen verständlichen Grund, warum die Daten nicht in das div eingetragen werden? Wenn ich statt dessen ein alert oder einen console.log mache, wird das ja auch ausgeführt.
 

Sempervivum

Erfahrenes Mitglied
Mir ist kein Weg bekannt, wie man auf den teilweise herunter geladenen Inhalt zugreifen kann. Der Grund ist wahrscheinlich, dass das Herunterladen für beliebige Inhalte funktionieren muss und wenn es sich z. B. um Binärdaten handelt, könnte man nichts damit anfangen wenn sie unvollständig sind.

Du kannst die Daten jedoch auf dem Server in Abschnitte unterteilen und nach für nach herunter laden. Das ist auch ein gängiges Verfahren und wird häufig als "Paging" bezeichnet. Dann kannst Du den Abschnitt, der gerade fertig ist, der Anzeige hinzu fügen.
 

Sempervivum

Erfahrenes Mitglied
... oder, wenn es sich um eine JSON-Datei handelt, kann man diese überhaupt nicht parsen, wenn sie unvollständig ist.
 

Sprint

Erfahrenes Mitglied
In der each() in Zeile 14 wird die Funktion getDaten() ja für jede einzelne Kundennummer aufgerufen und da kommt nur ok oder error zurück. Das sollte doch eigentlich reichen. Darum bin ich ja auch so verwirrt, daß das erst ganz am Ende erscheint.

Ich werde das nachher auch noch mal über eine Ausgabe der Rückgaben in die Konsole ausprobieren.
 

Sempervivum

Erfahrenes Mitglied
Oh, da habe ich mir deinen Code nicht genau genug angesehen: Du ermittelst anscheinend die Kunden für ein bestimmtes Land und holst dann für jeden Kunden eine Anzahl.

Hier könnte es Optimierungspotenzial auf der Serverseite geben: Die Anzahl durch die Datenbank mit COUNT ermitteln lassen und nach Kunde gruppieren.

Was ich noch nicht verstehe: In getDaten steht in der Serverantwort entweder ein String 'ok' oder etwas anderes. Was hat das zu bedeuten?

Aber ich glaube zu verstehen warum das mit der sofortigen Ausgabe bei dir nicht funktioniert: Du hast async auf false gesetzt, d. h. das Ganze spielt sich synchron ab. In dem Fall rendert der Browser wahrscheinlich die Ausgabe in #kdnrAusgabe erst wenn alle synchronen Vorgänge abgeschlossen sind.
 

Sempervivum

Erfahrenes Mitglied
PS: Ich habe das getestet und es hat sich bestätigt, dass die Ausgabe in #kdnrAusgabe erst gerendert wird, wenn alle synchronen Aufrufe durch sind. Hier bestätigt sich die Warnung, dass man eine Anfrage mit Ajax nicht synchron laufen lassen sollte.
 

Sempervivum

Erfahrenes Mitglied
PPS: Das Problem lässt sich lösen, indem man das moderne async-await verwendet, in dieser Demo wird dann sofort der Wert in #kdnrAusgabe angezeigt:
Code:
    <span id="kdnrAusgabe"></span>
    <script>
        async function getIt() {
            for (let i = 0; i < 10; i++) {
                data = await fetch("thread1060-ajax-sync.php").then(response => {
                    return response.text();
                });
                console.log(data);
                document.querySelector('#kdnrAusgabe').textContent = i;
            }
        }
        getIt();
    </script>
 
Status
Dieses Thema wurde gelöst! Zur Lösung gehen…