hics: Eine AJAX Abfrage nach der anderen ausführen?

Hallo Zusammen!

Ich habe gerade ein etwas mühsames Problem bei welchem ich nicht so recht weiss wie ich es lösen soll. Sorry für den langen Text, aber ich versuche das Problem so genau wie möglich zu Beschreiben:

Ich baue mir momentan eine Datenbank für meine Filme mit HTML (& CSS), PHP (& MySQL) und JavaScript. Von HTML und PHP habe ich schon ausreichend Vorwissen, in JavaScript habe ich mich erst mit diesem Projekt eingearbeitet.

Nun habe ich für diese Datenbank eine Seite bei welcher ich neue Filme eintragen kann. Damit ich nicht jeden Film einzeln eintragen muss, habe ich eine Textarea erstellt. In dieser Textarea kann ich auf jeder Zeile einen Film eintragen. Wenn ich dann auf einen Button klicke wird mir für jede eingetragene Zeile ein Textfeld mit dem entsprechenden Filmtitel erstellt. Diese Textfelder sind fortlaufend und eindeutig nummeriert (z.B. name="Filmtitel1" name="Filmtitel2" usw.)

Nun gibt es eine inoffizielle IMDb API bei welcher ich nach dem Filmtitel suchen kann und mir ein XML mit den jeweiligen anderen Werten (Erscheinungsjahr, Originaltitel, Bewertung, ...) liefert.

Ich würde jetzt gerne auf einen weiteren Knopfdruck diese drei Werte zu den jeweiligen Filmtiteln (in drei weiteren Textboxen) eintragen. Der Knackpunkt an der API ist, dass sie nur eine Abfrage gleichzeitig zulässt und es 1-2 Sekunden dauert bis die Werte verarbeitet sind.

Ich habe das ganze mit einer while Schleife versucht, aber dann werden nur die Werte für den letzten Film eingetragen. Ich vermute das liegt daran weil die while Schleife so schnell durchläuft, aber die Antwort des Servers so lange dauert.

Gibt es nun eine Möglichkeit eine Abfrage nach der anderen durchzuführen? Mir ist klar, dass der Benutzer unter Umständen in dieser Zeit nichts machen kann. Da aber die Datenbank eh nur von mir benutzt wird spielt das eigentlich keine Rolle, ich könnte das ganze auch mit einer Ladeanimation überbrücken.

Klar könnte ich einen Knopf für jede Zeile erstellen, aber mir wäre es lieber wenn ich alle Abfragen mit einem Knopfdruck erledigen könnte.

Grüsse

  1. Ich habe das ganze mit einer while Schleife versucht, aber dann werden nur die Werte für den letzten Film eingetragen. Ich vermute das liegt daran weil die while Schleife so schnell durchläuft, aber die Antwort des Servers so lange dauert.

    Ich vermute, du überschreibst dir etwas!

    Gibt es nun eine Möglichkeit eine Abfrage nach der anderen durchzuführen?

    Ja, starte den nächsten Request nachdem die Antwort des vorherigen in deinem Callback ausgewertet wurde.

    Mir ist klar, dass der Benutzer unter Umständen in dieser Zeit nichts machen kann.

    Das läuft doch asynchron?!

    1. Ich vermute, du überschreibst dir etwas!

      Ist so, sofern ich keinen Denkfehler mache. Kann das Script gerade nicht posten da ich auf der Arbeit bin, aber grundsätzlich läuft es so ab, dass jeweils der genau gleiche Request abläuft, nur mit jeweilig unterschiedlichem Wert (einmal dem Wert aus Feld mit name="Filmtitel1", dann name="Filmtitel2" etc.

      Gibt es nun eine Möglichkeit eine Abfrage nach der anderen durchzuführen?
      Ja, starte den nächsten Request nachdem die Antwort des vorherigen in deinem Callback ausgewertet wurde.

      Callback sagt mir momentan noch nichts, werde werde aber nachher oder heute Abend mal drüber nachlesen. Läuft dann die while Schleife gar nicht mehr weiter solange die Antwort im Callback nicht ausgewertet wurde, oder spielt das dann keine Rolle mehr? Momentan ist meines Wissens ja das Problem, dass der vorherige Request mit jedem Durchlauf der Schleife überschrieben wird und folglich wird nur der letzte Eingetragen.

      Das läuft doch asynchron?!

      Ja, theoretisch schon. Ich dachte nur, dass die while Schleife anhält wenn ich auf die Antwort warten muss und sich das Script in dieser Zeit "aufhängt".

      1. Tach!

        Ich vermute, du überschreibst dir etwas!
        Ist so, sofern ich keinen Denkfehler mache.

        Du kannst den Ablauf mit Kontrollausgaben prüfen. Lass dir was signifikantes an strategisch wichtigen Stellen ausgeben. alert() eignet sich vielleicht nicht so gut, denn bis du bestätigt hast, ist schon alles im Hintergrund gelaufen. Also besser die Ausgaben als Inhalt in ein Element schreiben.

        Gibt es nun eine Möglichkeit eine Abfrage nach der anderen durchzuführen?
        Ja, starte den nächsten Request nachdem die Antwort des vorherigen in deinem Callback ausgewertet wurde.
        Callback sagt mir momentan noch nichts, werde werde aber nachher oder heute Abend mal drüber nachlesen.

        Das solltest du, das ist essentiel für das Verständnis der beiden Ajax-Arbeitsweisen synchron vs. asynchron.

        Läuft dann die while Schleife gar nicht mehr weiter solange die Antwort im Callback nicht ausgewertet wurde, oder spielt das dann keine Rolle mehr?

        Der Callback wird an einer anderen Stelle und zu einer anderen Zeit ausgeführt.

        Das läuft doch asynchron?!
        Ja, theoretisch schon. Ich dachte nur, dass die while Schleife anhält wenn ich auf die Antwort warten muss und sich das Script in dieser Zeit "aufhängt".

        Bei asynchon hält nichts an, das ist ja das was man daran will. Der Aufruf ist abgesetzt und die nächste Codezeile wird abgearbeitet. Vom Request bekommt man erst durch den Callback wieder etwas zu sehen.

        dedlfix.

        1. Moin!

          Du kannst den Ablauf mit Kontrollausgaben prüfen. Lass dir was signifikantes an strategisch wichtigen Stellen ausgeben. alert() eignet sich vielleicht nicht so gut, denn bis du bestätigt hast, ist schon alles im Hintergrund gelaufen. Also besser die Ausgaben als Inhalt in ein Element schreiben.

          Werde ich mal machen, habs bisher nur mit alerts geprüft aber dieses Problem gar nicht bedacht. Bin halt noch etwas neu bei JavaScript.

          Das solltest du, das ist essentiel für das Verständnis der beiden Ajax-Arbeitsweisen synchron vs. asynchron.
          Der Callback wird an einer anderen Stelle und zu einer anderen Zeit ausgeführt.

          Achso, natürlich habe ich einen Callback drin. Mir sagte nur der Begriff nichts, da ich gestern das erste Mal mit ajax gearbeitet habe. Momentan befindet sich der Callback innerhalb der while Schleife, direkt unterhalb der restlichen ajax Befehle.

          Könnte ich jetzt theoretisch die Callback Funktion separat definieren und die Funktion jeweils bei einer Antwort aufrufen? In der Funktion könnte ich dann ja auch noch die Zeilennumer übergeben damit die Werte in die richtige Zeile eingetragen werden...

          Oder mache ich hier wieder einen Denkfehler?

          Achja, ich benutze einen "PHP Proxy" da ja cross site ajax Anfragen zwar den state == 4 aber status == 0 zurückgeben. Also übergebe ich die GET variablen an ein PHP file, welches durch diese die richtige Remote Serveraddresse erstellt und das XML File der API öffnet.

          1. Tach!

            Achso, natürlich habe ich einen Callback drin. Mir sagte nur der Begriff nichts, da ich gestern das erste Mal mit ajax gearbeitet habe. Momentan befindet sich der Callback innerhalb der while Schleife, direkt unterhalb der restlichen ajax Befehle.

            Wo du die Funktion platzierst, ist egal. Du musst nur eine Referenz darauf dem onreadystatechange zuweisen.

            Könnte ich jetzt theoretisch die Callback Funktion separat definieren und die Funktion jeweils bei einer Antwort aufrufen?

            Nicht du rufst den Callback auf, sondern der Browser ruft ihn auf, wenn er die Antwort empfangen hat (beziehungweise eine Statusänderung bekanntgeben will). Das ist genauso wie bei anderen Events: du wirst benachrichtigt, wenn etwas geschieht.

            In der Funktion könnte ich dann ja auch noch die Zeilennumer übergeben damit die Werte in die richtige Zeile eingetragen werden...

            Da der Rückruf irgendwann später kommt, musst du irgendwie eine Zuordnung zum Aufruf hinbekommen. Entweder kannst du diese Information aus der Response lesen (vielleicht indem du etwas eindeutiges im Request mitschickst und in der Response wieder zurück) oder du verwaltest das auf Javascript-Ebene (vielleicht mit Closure - dazu eine Literaturempfehlung).

            dedlfix.

      2. Hallo hics,

        Callback sagt mir momentan noch nichts

        Das ist der m.E. richtige Hinweis gewesen. Vergiss mal die while Schleife auf Serverseite. Die Ajaxfunktionen müssen sich selbst aufrufen, sonst können sie nicht nacheinander ausgeführt werden. Kurzerklärung:
        AJAX besteht ja im Prinzip aus drei Teilen: 1) Request Objekt erstellen, 2) Requestfunktion, 3) Callbackfunktion.

        1. Requestobjekt erstellen, mit Browserweiche. Findest Du in einem Einsteigerturorial. Variable heisst dann zum Beispiel AjaxRequestObject (für dieses Beispiel).
        2. Requestfunktion enthält unter anderem den Teil
          AjaxRequestObject.open(method, url, asynch);
          zum Definieren des Requests aber auch
          AjaxRequestObject.onreadystatechange = AjaxRequestObjectHandle;
          zum Definieren der Callbackfunktion, hier AjaxRequestObjectHandle(). (Achtung ohne () hinter der Zuweisung, sonst wird sie gleich ausgeführt).
        3. Die Callbackfunktion wird ausgeführt, sobald sich der Zustand des Requestobjekts geändert hat "onreadystatechange". Das passiert öfter während des gesamten Requests. Wichtig ist aber meistens _die erfolgreiche Beendigung_ des Requests, daher musst du in der Callbackfunktion erstmal .readyState == 4 und .status == 200 prüfen, aber das findest Du in den Einsteigertutorials.

        Dann kannst du in der Callbackfunktion bei readyState==4 und .status==200 erneut die AjaxRequest-Funktion ausführen. Wichtig wäre dabei aber noch einen geeigneten Rückgabewert einzuführen, auf den reagiert wird, da die Requests sonst endlos aufgerufen werden. D.h. in das aufgerufene Script muss eine Prüfung rein, ob es weitere Requests geben soll, und dann wird ein entsprechender Wert zurückgegeben. In der Callbackfunktion kannst du mit z.B. .responseText auf diesen Rückgabewert reagieren. Wenn das Script mehrere/viele Werte zurückgibt, besser gleich mit JASON, xml,... in den Rückgabewerten arbeiten und .responseXML,...

        Cheers,
        Baba

        1. Hallo Baba, vielen Dank für deine ausführliche Antwort!

          Das ist der m.E. richtige Hinweis gewesen. Vergiss mal die while Schleife auf Serverseite.

          Die while Schleife läuft im JavaScript, also auf Seite des Clients ab. Da ich ja eine unbekannte Anzahl von Zeilen (und folglich Textfeldern) habe, läuft die while Schleife so lange durch wie noch eine weitere Zeile existiert.

          Die Ajaxfunktionen müssen sich selbst aufrufen, sonst können sie nicht nacheinander ausgeführt werden. Kurzerklärung:
          AJAX besteht ja im Prinzip aus drei Teilen: 1) Request Objekt erstellen, 2) Requestfunktion, 3) Callbackfunktion.

          Wie ich bereits in einer anderen Antwort geschrieben habe sind die Callbackfunktion vorhanden, mir sagte nur auf die Schnelle der Begriff nichts. Momentan befindet sich der Callback innerhalb der while Schleife, direkt unterhalb der restlichen ajax Befehle. Und ich glaube da liegt mein Fehler.

          Könnte ich jetzt theoretisch die Callback Funktion separat definieren und die Funktion jeweils bei einer Antwort aufrufen? In der Funktion könnte ich dann ja auch noch die Zeilennumer übergeben damit die Werte in die richtige Zeile eingetragen werden...

          Oder mache ich hier wieder einen Denkfehler?

          Achja, ich benutze einen "PHP Proxy" da ja cross site ajax Anfragen zwar den state == 4 aber status == 0 zurückgeben. Also übergebe ich die GET variablen an ein PHP file, welches durch diese die richtige Remote Serveraddresse erstellt und das XML File (fopen etc.) der API öffnet.

          Gruss
          hics

          1. Könnte ich jetzt theoretisch die Callback Funktion separat definieren

            Ja, solltest Du separat definieren! Kann alles separat sein. Ich mag es z.B auch nicht, wenn das Objekt selbst (mit Browserweiche und allem) in der Requestfunktion erzeugt wird. Kann auch separat, mit einer Funktion, erzeugt werden.

            und die Funktion jeweils bei einer Antwort aufrufen?

            Die Callbackfunktion wird wie gesagt automatisch bei onreadystatechange aufgerufen. Also "eine Antwort" gibt es nicht, es gibt "viele Antworten". Die, die du vermutlich meinst ist die .readyState == 4, etc.

            In der Funktion könnte ich dann ja auch noch die Zeilennumer übergeben damit die Werte in die richtige Zeile eingetragen werden...

            Der Callbackfunktion kann kein Parameter direkt mitgegeben werden (siehe .onreadystatechange = Funktion; ohne ())
            Die Zeilenummer kannst Du der Callbackfunktion aber trotzdem übergeben, als Antwort vom Script. Wenn das die einzige Rückgabe ist, kannst Du sie mittels .responseText lesen, und darauf reagieren. Besser aber, die Rückgabe ist ein xml, dann responseXML und dies richtig interpretieren.

            Aber das meintest Du besimmt.

            Bei Fragen einfach wieder schreiben.

            Cheers,
            Baba

            1. Der Callbackfunktion kann kein Parameter direkt mitgegeben werden (siehe .onreadystatechange = Funktion; ohne ())
              Die Zeilenummer kannst Du der Callbackfunktion aber trotzdem übergeben, als Antwort vom Script. Wenn das die einzige Rückgabe ist, kannst Du sie mittels .responseText lesen, und darauf reagieren. Besser aber, die Rückgabe ist ein xml, dann responseXML und dies richtig interpretieren.

              Aber das meintest Du besimmt.

              Bei Fragen einfach wieder schreiben.

              Cheers,
              Baba

              Vielen Dank, muss mir das heute Abend mal nochmal genauer anschauen. Ist immer einfacher wenn ich vor dem Code sitze als wenn ich mir das im Kopf vorstellen muss.

              Nur wie ich die Zeilennummer weitergebe leuchtet mir noch nicht so ganz ein, aber das schaffe ich auch noch.

              Grüsse

  2. hi,

    Klar könnte ich einen Knopf für jede Zeile erstellen, aber mir wäre es lieber wenn ich alle Abfragen mit einem Knopfdruck erledigen könnte.

    Würde ich auch so machen. Der Request sendet die komplette Textarea, ggf. weitere Felder und serverseitig wird das dann geparst und eingetragen.

    Es ist völlig unerheblich, ob der Request mit Ajax erfolgt oder per Submit.

    Andererseits wäre es schon möglich, mit Ajax Zeile für Zeile einen Request zu feuern, aber einen Sinn sehe ich darin nicht.

    Hotti

    1. Würde ich auch so machen. Der Request sendet die komplette Textarea, ggf. weitere Felder und serverseitig wird das dann geparst und eingetragen.

      Die Textarea wird in verschiedene Zeilen gesplittet. Da kann ich auch die restlichen Werte eintragen (z.B. auf welchem Medium sich der Film befindet). Für diese Zeilen sollen die Abfragen nach und nach stattfinden. Danach kann ich das ganze Formular "abschicken", wodurch es von PHP auf seine Richtigkeit geprüft und in die Datenbank eingetragen wird.

      Es ist völlig unerheblich, ob der Request mit Ajax erfolgt oder per Submit.

      Wie meinst du das? Also so wie ich mir das gedacht habe wird der Request dann nicht in einer Schleife ablaufen sondern einfach jeweils per Knopfdruck für die jeweilige Zeile (in dem ich eine Funktion aufrufe).

      Andererseits wäre es schon möglich, mit Ajax Zeile für Zeile einen Request zu feuern, aber einen Sinn sehe ich darin nicht.

      Der Sinn für mich wäre, dass ich nicht für jede Zeile einen Knopf drücken muss. Vielleicht ist das nur Faulheit, aber es wäre halt komfortabler wenn mit einem Knopfdruck Zeile nach Zeile durchlaufen würde.

      Deswegen nehme ich auch den "Umweg" mit der Textarea. Ich habe viele Filme schon in irgendwelchen Files und kann sie so komfortabel per Copy/Paste in meine Datenbank übertragen.

      1. hi,

        Deswegen nehme ich auch den "Umweg" mit der Textarea. Ich habe viele Filme schon in irgendwelchen Files und kann sie so komfortabel per Copy/Paste in meine Datenbank übertragen.

        Idee: Die Dateien gar nicht erst über den Mauszeiger ziehen, sondern direkt oder nach einem Upload verarbeiten (kommt natürlich drauf an, wie die Dateien aufgebaut sind). Das wär was für mich hehe ;)

        Hotti

        --
        Wenn der Kommentar nicht zum Code passt, kann auch der Code falsch sein.
        1. Idee: Die Dateien gar nicht erst über den Mauszeiger ziehen, sondern direkt oder nach einem Upload verarbeiten (kommt natürlich drauf an, wie die Dateien aufgebaut sind). Das wär was für mich hehe ;)

          Wäre zwar durchaus eine Möglichkeit, aber das ajax Problem hätte ich dann nach wie vor ;) Ausserdem sind das Excel Files, welche ja eh (mehr oder weniger) proprietär sind. Da ist File öffnen -> Bereich anwählen -> Copy -> zu Browser wechseln -> Paste etwas einfacher.

          1. Idee: Die Dateien gar nicht erst über den Mauszeiger ziehen, sondern direkt oder nach einem Upload verarbeiten (kommt natürlich drauf an, wie die Dateien aufgebaut sind). Das wär was für mich hehe ;)
            Wäre zwar durchaus eine Möglichkeit, aber das ajax Problem hätte ich dann nach wie vor ;) Ausserdem sind das Excel Files, welche ja eh (mehr oder weniger) proprietär sind. Da ist File öffnen -> Bereich anwählen -> Copy -> zu Browser wechseln -> Paste etwas einfacher.

            Nixda :)
            Die Exceldateien werden lokal mit Perl verarbeitet, da wird z.B. ne INI oder ne Binärsequenz draus gemacht und ab gehts zum Server...

            Hotti

            --
            Wenn der Kommentar nicht zum Code passt, kann auch der Code falsch sein.
            1. Nixda :)
              Die Exceldateien werden lokal mit Perl verarbeitet, da wird z.B. ne INI oder ne Binärsequenz draus gemacht und ab gehts zum Server...

              Und wie hole ich dann die Daten von der IMDb API?
              Wär zwar durchaus eine (schöne) Möglichkeit, aber dann müsste ich wohl einige Teile meines bisherigen Scripts umschreiben. Ausserdem habe ich absolut keine Ahnung von Perl. Da mache ich dann wohl doch eher die Variante mit dem Knopf / Link pro Zeile :)

              Gruss