Frage Ajax-Schleifendurchläufe (asynchron) zählen

  • Jetzt anmelden. Es dauert nur 2 Minuten und ist kostenlos!

Dieter!

Neues Mitglied
8 Juni 2021
26
0
1
Oldenburg
Hallo,

ich versuche hier die erfolgreichen Datenbank-INSERTs zu zählen, bekomme aber in dem alert() immer "0" zurück.

Javascript:
            function jsVorlageSpeichern()
            {
                $("#kreisel").html("<img src='images/kreisel.gif' />");                                    // Kreisel anzeigen
                var inserts = 0;
                
                $("#speiseplanung textarea").each(function(pos, textarea)       
                {
                        let DATA = {  
                            tagID: textarea.name.split("][")[2],
                            artikelnummer: $("#artikelnummer" + textarea.name.split("][")[2]).val(),
                            menueText: textarea.value
                         };        

                    if (textarea.value.trim())
                    {
                        $.post("ajax/ajaxMenueplanVorlageSpeichern.php", DATA, function(phpData) { if (phpData==1)  {  inserts++;  } }

                        console.log("inserts nach  $.post: ",  inserts);  // hier werden nacheinander alle INSERTs ausgegeben
                    }
                }                         );

                $("#kreisel").html("");                    // Kreisel ausblenden
                alert('Die Vorlage wurde mit ' + inserts + ' Artikeln gespeichert.');  // hier ist "inserts" immer "0"
            }

Ich verstehe die asynchrone Abarbeitung so, dass die Ajax-$.posts in der Schleife "angetriggert" werden, aber alert() schon ausgegeben wird bevor die DB Anweisungen abgeschlossen sind. Aber wie kann ich nun die erfolgreichen Datenbank-INSERTs zählen?

Im nächsten Schritt möchte ich dann ein Spinner/Kreisel vom Start bis Ende anzeigen lassen. Ich vermute, dass der auch wegen der asynchrone Abarbeitung so nicht funktioniert.

Vielen Dank schonmal für eure Hilfe.
 

Sempervivum

Senior HTML'ler
18 Oktober 2016
2.456
466
83
68
Ich verstehe die asynchrone Abarbeitung so, dass die Ajax-$.posts in der Schleife "angetriggert" werden, aber alert() schon ausgegeben wird bevor die DB Anweisungen abgeschlossen sind.
Das ist genau der Grund, warum es so nicht funktioniert.
Lösung indem Du die Anzahl der Requests ermittelst und im Callback, d. h. wenn die Antwort vom Server da ist, prüfst, ob alle Antworten da sind. Ist das der Fall, liegt die vollständige Anzahl der Inserts vor und Du kannst damit arbeiten.
BTW: Mein Editor hat in deinem Code einen Syntaxfehler beanstandet. Besser sinnvoll einrücken, damit man einen Überblick über die Struktur behält.
Ungetestet:
Code:
        function jsVorlageSpeichern() {
            $("#kreisel").html("<img src='images/kreisel.gif' />");                                    // Kreisel anzeigen
            let requests = 0,
                responses = 0,
                inserts = 0;
            $("#speiseplanung textarea").each(function (pos, textarea) {
                let DATA = {
                    tagID: textarea.name.split("][")[2],
                    artikelnummer: $("#artikelnummer" + textarea.name.split("][")[2]).val(),
                    menueText: textarea.value
                };

                if (textarea.value.trim()) {
                    // Anfragen an der Server erhoehen, dies geschieht synchron
                    requests++;
                    $.post("ajax/ajaxMenueplanVorlageSpeichern.php",
                        DATA,
                        function (phpData) {
                            if (phpData == 1) {
                                inserts++;
                                console.log("inserts nach  $.post: ", inserts);  // hier werden nacheinander alle INSERTs ausgegeben
                            }
                            // Anzahl der Antworten erhoehen:
                            responses++;
                            // Pruefen ob alle Antworten vom Server das sind:
                            if (responses == requests) {
                                $("#kreisel").html("");                    // Kreisel ausblenden
                                alert('Die Vorlage wurde mit ' + inserts + ' Artikeln gespeichert.');
                            }
                        });
                }
            });
        }
Ich glaube, async/await unterstützt mehrere Requests und erkennt, wenn alles Antworten da sind. Da müsste man sich mal mit vertraut machen, damit man sich die Zählerei sparen kann.
 

Dieter!

Neues Mitglied
8 Juni 2021
26
0
1
Oldenburg
Super, vielen herzlichen Dank, das funktioniert perfekt.
Schön verrückt dies Asynchrone. Ich hatte zuvor $.ajax() mit async:false verwendet. Das war einfacher, sollte aber wohl, so wie ich das verstanden, habe, nicht mehr verwendet werden.
 

Sempervivum

Senior HTML'ler
18 Oktober 2016
2.456
466
83
68
PS, ich schrieb:
Ich glaube, async/await unterstützt mehrere Requests und erkennt, wenn alles Antworten da sind.
Ich habe mir das mal angesehen und muss mich korrigieren: Das Abwarten mehrerer Requests beruht auf Promise.all und funktioniert sowohl mit .then als auch mit async/await, ist also nicht an letzteres gebunden.
 

Sempervivum

Senior HTML'ler
18 Oktober 2016
2.456
466
83
68
habe ich mal probiert ein $.when( ... ).then... über die each-Schleife zu stülpen, ohne Erfolg.
Ich wusste noch gar nicht, dass es das auch in jQuery gibt, danke für diesen Hinweis.
Hast Du es so versucht:
Code:
        function jsVorlageSpeichern() {
            $("#kreisel").html("<img src='images/kreisel.gif' />");                                    // Kreisel anzeigen
            let promises = [];
            // Zunaechst bereiten wir ein Array mit den Promises vor:
            $("#speiseplanung textarea").each(function (pos, textarea) {
                if (textarea.value.trim()) {
                    // POST-Parameter bereit stellen:
                    let DATA = {
                        tagID: textarea.name.split("][")[2],
                        artikelnummer: $("#artikelnummer" + textarea.name.split("][")[2]).val(),
                        menueText: textarea.value
                    };
                    // Textarea ist nicht leer, Promise in Array eintragen:
                    promises.push(
                        $.post("ajax/ajaxMenueplanVorlageSpeichern.php", DATA)
                    );
                }
            });

            // Anfragen an den Server ausfuehren indem wir
            // $.when mit den Promises als Argumenten aufrufen:
            $.when.apply($, promises).then(function () {
                // Die Antworten vom Server stehen jetzt in der Argumentliste
                // dieser anonymen Funktion:
                console.log(arguments);
                // Wir arbeiten die Argumente ab um die Anzahl der Inserts zu bestimmen:
                let inserts = 0;
                $.each(arguments, function (idx, item) {
                    if (item[0] == 1) {
                        inserts++;
                    }
                });
                $("#kreisel").html(""); // Kreisel ausblenden
                alert('Die Vorlage wurde mit ' + inserts + ' Artikeln gespeichert.');
            });
        }
Ungetestet, weil ich nicht genau wusste, wie die name-Attribute deiner Textareas aussehen. Diese Demo funktioniert:
Code:
        const params = [1, 2, 3, 4, 5];
        let promises = [];
        $.each(params, function (idx, item) {
            promises.push(
                $.ajax({
                    url: 'promise-all.php',
                    data: { param1: item },
                    method: 'POST'
                })
            );
        });

        $.when.apply($, promises).then(function () {
            console.log(arguments);
            $.each(arguments, function (idx, item) {
                console.log(item[0]);
            });
        });
IMO ist die Version mit $.when oder Promise.all auf jeden Fall eleganter aber auf den ersten Blick etwas kryptisch. Aber wahrscheinlich nur eine Frage der Gewöhnung.
 

Dieter!

Neues Mitglied
8 Juni 2021
26
0
1
Oldenburg
So hatte ich das natürlich nicht versucht. Ich weiß auch auch nicht ob ich mich jemals an dies Kryptische gewöhne. Auf jeden Fall funktioniert es wieder mal super und ich lass auch diese elegantere Variante in meinem Programm.
Was soll ich sagen, nochmal ganz herzlichen Dank für deine Hilfe.