moO: $.get in schleife -.-

Hi alle,

ich habe ein kleines Problem mit jquery:
hier erstmal das script:

  
var values = new Array("Wert1", "Wert2");  
     $('#weekSelect').change(function(){  
          week=$(this).val();  
          for(i=0;i<values.length;i++){  
          var keyVal=trackedValues[i];  
          alert(keyVal); //1. Alert  
          $.get(    "test.php",  
                    {task:"fetchWeekData", week:week, key:keyVal},  
                    function(data){  
                         idKey="#"+keyVal;  
                         alert(idKey); //2. Alert  
                         $(idKey).html(data);  
                         });  
          }  
     });

Das Ding soll also so oft in einer Schleife laufen wie es Werte im Array gibt.
Problem ist, dass, wenn ich die alerts laufen lasse, ich erst zweimal das erste Alert gezeigt bekomme und dann zweimal das zweite Alert, er das $.get also nicht direkt ausführt wenn es in der schleife dran wäre, sondern erst hinterher und damit ist 'keyVal' immer "Wert2", statt erst "Wert1" und dann "Wert2".

Wo ist der Fehler? Von mir mal abgesehen :D

  1. Tach auch.

    Das Ding soll also so oft in einer Schleife laufen wie es Werte im Array gibt.
    Problem ist, dass, wenn ich die alerts laufen lasse, ich erst zweimal das erste Alert gezeigt bekomme und dann zweimal das zweite Alert, er das $.get also nicht direkt ausführt wenn es in der schleife dran wäre, sondern erst hinterher und damit ist 'keyVal' immer "Wert2", statt erst "Wert1" und dann "Wert2".

    Wo ist der Fehler? Von mir mal abgesehen :D

    Die von dir eingesetzte Technologie heißt AJAX, dass erste A steht für asynchronous.

    Du kannst z.B. den Request auf synchron stellen, oder den zweiten Request erst starten, wenn der erste fertig ist, indem du den Request im onreadystatechange-Handler des ersten Requests startest.

    Bis die Tage,
    Matti

    1. Die von dir eingesetzte Technologie heißt AJAX, dass erste A steht für asynchronous.

      Ich weiß ;)

      Du kannst z.B. den Request auf synchron stellen, ...

      Das weiß ich nicht ;p Wie mache ich das und welche Auswirkungen hat das?
      Die Aktualisierung soll ja laufen ohne das ich die Seite neu aufbauen muss.

      oder den zweiten Request erst starten, wenn der erste fertig ist, indem du den Request im onreadystatechange-Handler des ersten Requests startest.

      Wie würde das in diesem Falle aussehen? Unter Berücksichtigung, das das values-array beliebig gross werden kann?

      1. Tach auch.

        Du kannst z.B. den Request auf synchron stellen, ...

        Das weiß ich nicht ;p Wie mache ich das und welche Auswirkungen hat das?
        Die Aktualisierung soll ja laufen ohne das ich die Seite neu aufbauen muss.

        jQuery bietet dir die entsprechenden Möglichkeiten: $.ajax() beschreibt das Setting "async", welches standardmäßig auf "true" steht. Stell das halt ab.

        Ich habs nie probiert, aber ich erwarte, dass der Seitenaufbau (bzw. zumindest Javascript) solange stoppt, bis der Request abgearbeitet ist.

        oder den zweiten Request erst starten, wenn der erste fertig ist, indem du den Request im onreadystatechange-Handler des ersten Requests startest.
        Wie würde das in diesem Falle aussehen? Unter Berücksichtigung, das das values-array beliebig gross werden kann?

        Du baust eine Queue auf (Implementierung über ein Array). Zunächst holst du dir das erste Element (und shiftest dann) und startest mit diesem Element den ersten Request.

        Am Ende des Requests (im onsuccess-handler) holst du dir wiederum das erste und startest einen neuen Request mit diesem Element (Array shiften nicht vergessen). USWUSF bis die Queue leer ist.

        Bis die Tage,
        Matti

        1. ooook, nachem ich ein simples
          $.ajaxSetup({async:false});
          eingefügt habe läuft es wie im traum :)

          DANKE DIR!!

          (ich würde das dankeschön auch doppelposten, aber da bekommt man bestimmt ärger ;p)

      2. Hi,

        [synchrone HTTP-Requests in einer Schleife über ein Array]

        Wie würde das in diesem Falle aussehen? Unter Berücksichtigung, das das values-array beliebig gross werden kann?

        in diesem Fall werden die meisten Browser nach kurzer Zeit anbieten, das Script zu stoppen. Du möchtest Dir eine effizientere Methodik des Datenaustausches überlegen.

        Cheatah

        --
        X-Self-Code: sh:( fo:} ch:~ rl:| br:> n4:& ie:% mo:) va:) de:] zu:) fl:{ ss:) ls:~ js:|
        X-Self-Code-Url: http://emmanuel.dammerer.at/selfcode.html
        X-Will-Answer-Email: No
        X-Please-Search-Archive-First: Absolutely Yes
    2. Hallo Matti,

      das ist nun schon das zweite Mal heute vormittag, dass du dasselbe Posting doppelt absendest (ich hab beide Duplikate gelöscht). Ich unterstelle dir keine Doppelposting-Absicht, aber achte bitte mal drauf. Was könnte die Ursache sein? Prellt deine Maus? Klickst du reflexartig zweimal auf "Nachricht absenden"? Macht dein Browser irgendeinen Mist?

      Schönen Tag noch,
       Martin

      --
      PCMCIA: People Can't Memorize Computer Industry Acronyms
      Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
      1. Tach auch.

        das ist nun schon das zweite Mal heute vormittag, dass du dasselbe Posting doppelt absendest (ich hab beide Duplikate gelöscht). Ich unterstelle dir keine Doppelposting-Absicht, aber achte bitte mal drauf. Was könnte die Ursache sein? Prellt deine Maus? Klickst du reflexartig zweimal auf "Nachricht absenden"? Macht dein Browser irgendeinen Mist?

        Ist mir sehr peinlich. Ich sitze in der neuen Bude meines Bruders und warte für ihn auf einen Telekomiker (oder Alice im kleinen Roten, kA) und surfe über über UMTS. Und manchmal bricht die Verbindung ab. Ich schaue zwar immer, ob das Posting schon angekommen ist, bevor ich es nochmal abschicke, aber ich habe anscheinend den Cache o.ä. vergessen.

        Wie auch immer: der Termin (0800 bis 1200 Uhr) ist jetzt rum, niemand war da :-(
        Jetzt kann ich wenigstens in Ruhe essen gehen.

        Bis die Tage,
        Matti

        1. Hallo,

          das ist nun schon das zweite Mal heute vormittag, dass du dasselbe Posting doppelt absendest [...]
          Ist mir sehr peinlich.

          muss es nicht, keine Sorge. Ich wollte dich nur darauf aufmerksam machen.

          Ich sitze in der neuen Bude meines Bruders und warte für ihn auf einen Telekomiker (oder Alice im kleinen Roten, kA) und surfe über über UMTS. Und manchmal bricht die Verbindung ab. Ich schaue zwar immer, ob das Posting schon angekommen ist, bevor ich es nochmal abschicke, aber ich habe anscheinend den Cache o.ä. vergessen.

          Alice im kleinen Roten? Jetzt wird's interessant. ;-)
          Wie auch immer, jetzt ist klar, woher's kommt. Ist ja auch nicht wirklich schlimm.

          Wie auch immer: der Termin (0800 bis 1200 Uhr) ist jetzt rum, niemand war da :-(
          Jetzt kann ich wenigstens in Ruhe essen gehen.

          Na, täusch dich nicht. Die Jungs von der Telekom haben eine seltsame Zeitskala. Mir haben sie auch mal einen Termin "gleich früh zwischen 8 und 9 Uhr" zugesagt, und tatsächlich kam der Bursche dann kurz vor zwölf. Und dann zeigte er mir noch seinen Einsatzplan, auf dem nur "vormittag" stand, und erklärte mir, dass die Techniker für ihre Vor-Ort-Einsätze niemals genauere Vorgaben als "vormittags" oder "nachmittags" bekämen, und ihre Runde anhand dieser Vorgaben nach eigenem Ermessen planen.

          Viel Glück noch,
           Martin

          --
          Es gibt Dinge, die sind sooo falsch, dass nicht einmal das Gegenteil stimmt.
          Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
          1. Na, täusch dich nicht. Die Jungs von der Telekom haben eine seltsame Zeitskala. Mir haben sie auch mal einen Termin "gleich früh zwischen 8 und 9 Uhr" zugesagt, und tatsächlich kam der Bursche dann kurz vor zwölf. Und dann zeigte er mir noch seinen Einsatzplan, auf dem nur "vormittag" stand, und erklärte mir, dass die Techniker für ihre Vor-Ort-Einsätze niemals genauere Vorgaben als "vormittags" oder "nachmittags" bekämen, und ihre Runde anhand dieser Vorgaben nach eigenem Ermessen planen.

            Mir haben sie sogar gesagt dass ich zwischen 8 und 16Uhr daheim sein soll.
            Es sei zwar sehr wahrscheinlich dass er zwischen 8 und 13Uhr kommt, aber es könnte auch 16Uhr werden...

            --
            for your security, this text has been encrypted by ROT13 twice.
            1. Tach auch.

              Mir haben sie sogar gesagt dass ich zwischen 8 und 16Uhr daheim sein soll.
              Es sei zwar sehr wahrscheinlich dass er zwischen 8 und 13Uhr kommt, aber es könnte auch 16Uhr werden...

              In meinem Fall war es so, dass im Brief 08:00 Uhr bis 12:00 Uhr drin steht. Ich empfinde dass sowieso schon als eine unverschämt lange Dauer (für einen 10 Minuten DSL-Anstöpsel-Termin!), und dann nichtmal zu kommen schlägt dem Fass den Boden aus.

              Ich bin gewillt, dem Provider meines Bruders eine Rechnung zu schicken für die unnötige Wartezeit (oder für die Wartezeit beim nächsten Termin). Heute hats mir gelangt, ich habe auch noch besseres zu tun als in der kalten Bude rumzuhocken.

              Bis die Tage,
              Matti

    3. Hallo,

      Du kannst z.B. den Request auf synchron stellen

      Das ist in 99% der Fälle das Letzte, was man will. Damit wird aus AJAX nicht SJAX, sondern Quatsch, weil man das gesamte User Interface grundlos einfriert, und das - bei mehreren Requests - auch noch mehrfach hintereinander.
      JavaScript funktioniert an sich asynchron, eventbasiert und funktional. Es gibt eine einzige Queue mit Code bzw. Funktionen, die nach und nach abgearbeitet werden. Diese Ausführung mit alert, confirm, synchronem XHR usw. global anzuhalten, um Synchronität zu erzwingen, sollte man möglichst vermeiden, sonst kommt schräger JS-Code heraus sowie ein ständig geblocktes Interface.

      oder den zweiten Request erst starten, wenn der erste fertig ist, indem du den Request im onreadystatechange-Handler des ersten Requests startest.

      Auch das scheint hier unnötig. Technisch gesehen sind die Requests unabhängig voneinander. Der zweite Request hängt nicht vom Ergebnis des ersten ab und muss auch nicht nach diesem passieren. Wieso sollte man hier eine Queue verwenden? Hier sollen - soweit das aus dem Quelltext ersichtlich ist - doch nur irgendwelche Elemente mit vom Server generierten Code gefüllt werden. Ich vermute nicht, dass dies strikt nacheinander passieren muss.

      Mathias

      1. Tach auch.

        oder den zweiten Request erst starten, wenn der erste fertig ist, indem du den Request im onreadystatechange-Handler des ersten Requests startest.

        Auch das scheint hier unnötig. Technisch gesehen sind die Requests unabhängig voneinander. Der zweite Request hängt nicht vom Ergebnis des ersten ab und muss auch nicht nach diesem passieren. Wieso sollte man hier eine Queue verwenden? Hier sollen - soweit das aus dem Quelltext ersichtlich ist - doch nur irgendwelche Elemente mit vom Server generierten Code gefüllt werden. Ich vermute nicht, dass dies strikt nacheinander passieren muss.

        Wichtig hierbei ist die Annahme, dass die Requests (bzw. die Ergebnisse) voneinander unabhängig sind. Das kann ich von meiner Seite aus nicht beurteilen. Der TE klingt so, als ob die "Sequenzialität" wichtig ist.
        Ist dies nur ein zunächst unangenehm erscheinender Nebeneffekt, sollte man mit dem ursprünglichen Verhalten leben.

        In jedem Fall sollte man aber überprüfen, ob man nicht alle Requests auf einmal stellen kann. Dann kann sich der Server mit der Reihenfolge herumschlagen und man deutlich weniger Request-Overhead.

        Bis die Tage,
        Matti

        1. In jedem Fall sollte man aber überprüfen, ob man nicht alle Requests auf einmal stellen kann. Dann kann sich der Server mit der Reihenfolge herumschlagen und man deutlich weniger Request-Overhead.

          Das ist ein sehr guter Tipp »unter Berücksichtigung, das das values-array beliebig gross werden kann« (OP). In dem Fall wäre vielleicht eine JSON-Serverantwort nützlich, die einem die verschiedenen HTML-Snippets strukturiert zurückgibt.

          Mathias

  2. var values = new Array("Wert1", "Wert2");
         $('#weekSelect').change(function(){
              week=$(this).val();
              for(i=0;i<values.length;i++){
              var keyVal=trackedValues[i];
              alert(keyVal); //1. Alert
              $.get(    "test.php",
                        {task:"fetchWeekData", week:week, key:keyVal},
                        function(data){
                             idKey="#"+keyVal;
                             alert(idKey); //2. Alert
                             $(idKey).html(data);
                             });
              }
         });

      
    Das sieht wie das typische Problem »Funktion (Closure) in Schleife erzeugen« aus, das wurde hier im Forum schon dutzende Male diskutiert.  
      
    Der Callback-Funktion wird ausgeführt, wenn die Schleife durchgelaufen ist. Die Lösung sollte möglichst NICHT sein, auf asynchrone Ajax-Requests umzusteigen. Wieso auch? Das macht die ganze Sache nur langsamer!  
      
    Die Lösung ist, der Funktion einfach die richtigen Werte zu übergeben. Dazu könnte man eine weitere anonyme Funktion notieren (das ist die Standardlösung):  
      
    ~~~javascript
    for (...) {  
      var keyVal = trackedValues[i];  
      (function (keyVal) {  
        $.get("test.php",  
              {task:"fetchWeekData", week:week, key:keyVal},  
              function(data) {  
                alert(keyVal);  
                $("#" + keyVal).html(data);  
              });  
      })(keyVal);  
    }
    

    Allerdings geht es hier etwas einfacher, ich würde den context-Parameter von jQuerys $.ajax() verwenden:

    for (...) {  
      var keyVal = trackedValues[i];  
      $.ajax({  
        url: "test.php",  
        data: {task: "fetchWeekData", week: week, key: keyVal}  
        context: keyVal,  
        success: function(data){  
          alert(this);  
          $("#" + this).html(data);  
        }  
      );  
    }
    

    Im Handler kann man dann über »this« auf das übergebene context-Objekt zugreifen. In dem Fall ist es wahrscheinlich nur ein String oder eine Number, aber das ist egal.

    Noch einfacher wäre e, im success-Handler auf data zugreifen zu können, denn darin steht der keyVal bereits. Aber ich wüsste nicht, wie das (ohne Closures) geht.

    Problem ist, dass, wenn ich die alerts laufen lasse, ich erst zweimal das erste Alert gezeigt bekomme und dann zweimal das zweite Alert, er das $.get also nicht direkt ausführt wenn es in der schleife dran wäre, sondern erst hinterher und damit ist 'keyVal' immer "Wert2", statt erst "Wert1" und dann "Wert2".

    Er muss den Code auch gar nicht hintereinander ausführen. Lass dich doch von den Alerts nicht verwirren. Alerts halten die JavaScript-Ausführung an. JavaScript und jQuery arbeiten aber fundamental asynchron. Das ist in Ordnung und an sich kein Problem.

    Zweck ist doch, irgendwelche Elemente mit HTML zu füllen, das vom Server kommt. Richtig? Die Reihenfolge ist doch egal. Wobei die Requests durchaus in der gewünschten Reihenfolge rausgehen und vermutlich auch die Antworten eintrudeln. Also kann das ruhig asynchron laufen. Die Asynchronität ist hier nicht das Problem, sondern die Datenverfügbarkeit durch Closures in JavaScript. Und das kannst du relativ einfach lösen.

    Mathias