CL: for-Schleife und Ajax

Guten Tag,
ich habe ein kleines Problem, wozu mir im Moment keine Lösung einfallen will.
Ich habe folgenden Code:

  
for(var i = 0; i < myArray.length - 1; i++) {  
	var URL = 'http://' + currentLang + '.site.de&format=json&callback=?';  
	descGet = $.getJSON(URL, {page: myArray[i]}, function(data) {  
		currentDescriptions[i] = data.test.replace(/\n*/g, '');  
	});  
	descGet.success(showResults);  
}  

Erklärung: Ich rufe mithile der jQuery Funktion getJSON(url, data, callback) mit verschiedenen, in dem Array "myArray" gespeicherten Parametern für "data" einen bestimmten Teil einer beliebigen JSONP-Struktur ab und versuche jede einzelne dieser Rückgaben mithilfe einer for-Schleife in dem Array für Beschreibungen "currentDescriptions" zu speichern. Zur Info: Die Funktion getJSON() gibt ein bestimmtes Objekt zurück, durch dieses kann man auch später noch den Callback (in diesem Fall mit success(), also bei Erfolg) definieren.
So nun zum Problem: Die Beschreibungen werden richtig abgerufen (getestet mithilfe von console.log(currentDescriptions[i];)) aber i ist hierbei jedesmal 12, also die Länge des Arrays "myArray". Ich persönlich kann mir nur vorstellen, dass die Schleife während dem Request weiterläuft. Wie könnte ich einstellen, dass die Schleife erst nach dem Ende des Requests weiterläuft?

Grüße, CL

--
ie:{ fl:) br:^ va:) ls:~ fo:| rl:( n4:& ss:| de:> js:) ch:| sh:} mo:} zu:(
  1. So nun zum Problem: Die Beschreibungen werden richtig abgerufen (getestet mithilfe von console.log(currentDescriptions[i];)) aber i ist hierbei jedesmal 12, also die Länge des Arrays "myArray". Ich persönlich kann mir nur vorstellen, dass die Schleife während dem Request weiterläuft. Wie könnte ich einstellen, dass die Schleife erst nach dem Ende des Requests weiterläuft?

    Das schreit nach einem Problem mit Synchroner und Asynchroner Ajax anfrage. Standardmässig ist die Asynchrone Anfrage eingestellt bei jquery. Das heißt, während der Anfrage läuft der Code weiter, so wie du berichtet hast.

    http://api.jquery.com/jQuery.ajax/

    Zitat:
    async
    Default: true

    By default, all requests are sent asynchronously (i.e. this is set to true by default). If you need synchronous requests, set this option to false. Cross-domain requests and dataType: "jsonp" requests do not support synchronous operation. Note that synchronous requests may temporarily lock the browser, disabling any actions while the request is active. As of jQuery 1.8, the use of async: false is deprecated.

    Gruß
    der asynchrone
    T-Rex

  2. Ich persönlich kann mir nur vorstellen, dass die Schleife während dem Request weiterläuft. Wie könnte ich einstellen, dass die Schleife erst nach dem Ende des Requests weiterläuft?

    Jedenfalls solltest du den Ajax-Request keinesfalls auf synchron umstellen.

    Das Grundproblem hier ist, dass du Funktionen (Closures) in einer Schleife erzeugst, die Funktion selbst aber asynchron aufgerufen wird, wenn die Schleife schon durchgelaufen ist. Daher ist i == 12. Zu den Suchbegriffen »Closure« und »Schleife« wirst du viele Einträge im Forumsarchiv finden.

    Hier sind unterschiedliche Lösungen denkbar, dazu müsste man die Rahmenumstände kennen. Allgemein kannst du den Zählerstand in die Funktion einschließen, indem du eine Closure erzeugst:

    var createCallback = function (i) {  
      // Erzeuge Closure, die den gegenwärtigen Wert von i einschließt  
      return function (data) {  
        currentDescriptions[i] = data.test.replace(/\n*/g, '');  
      });  
    };  
      
    for (...) {  
      descGet = $.getJSON(URL, {page: myArray[i]}, createCallback(i));  
      ...  
    }
    

    createCallback ist hier eine Funktion, die eine Funktion erzeugt.

    Mathias

    1. [...] Hier sind unterschiedliche Lösungen denkbar, dazu müsste man die Rahmenumstände kennen. Allgemein kannst du den Zählerstand in die Funktion einschließen, indem du eine Closure erzeugst:

      Klingt nach komplizierter Materie, mit der ich mich wohl einige Zeit auseinandersetzen werde.

      var createCallback = function (i) {

      // Erzeuge Closure, die den gegenwärtigen Wert von i einschließt
        return function (data) {
          currentDescriptions[i] = data.test.replace(/\n*/g, '');
        });
      };

      for (...) {
        descGet = $.getJSON(URL, {page: myArray[i]}, createCallback(i));
        ...
      }

      
      >   
      > createCallback ist hier eine Funktion, die eine Funktion erzeugt.  
        
      Meineswissens kann man im Callback von getJSON den Funktionen keine weiteren Parameter übergeben, ich bin mir allerdings nicht sicher.  
        
      Grüße, CL
      
      -- 
      ie:{ fl:) br:^ va:) ls:~ fo:| rl:( n4:& ss:| de:> js:) ch:| sh:} mo:} zu:( 
      
      1. @@CL:

        nuqneH

        Meineswissens kann man im Callback von getJSON den Funktionen keine weiteren Parameter übergeben,

        Wenn molily das sagt, dann kann man das auch. ;-)

        ich bin mir allerdings nicht sicher.

        Warum RTFMst du dann nicht?

        Qapla'

        --
        Wer möchte nicht lieber durch Glück dümmer als durch Schaden klüger werden? (Salvador Dalí)
        1. Hi

          Warum RTFMst du dann nicht?

          weil ich das bereits gemacht habe ;) Dort steht kein kein Beispiel, aber molily hat tatsächlich recht, da die Variable aufgerufen wird. Trotzdem steige ich nicht komplett durch, ich werde mich, wie gesagt, damit auseinandersetzen.

          Grüße, CL

          --
          ie:{ fl:) br:^ va:) ls:~ fo:| rl:( n4:& ss:| de:> js:) ch:| sh:} mo:} zu:(
          1. @@CL:

            nuqneH

            Warum RTFMst du dann nicht?
            weil ich das bereits gemacht habe ;) Dort steht kein kein Beispiel

            Ach, an den Englischkenntnissen hapert’s. „Beispiel“ heißt auf englisch „example“. Vielleicht clickst du mal auf den derart beschrifteten Reiter …

            Qapla'

            --
            Wer möchte nicht lieber durch Glück dümmer als durch Schaden klüger werden? (Salvador Dalí)
            1. Hallo,

              Ach, an den Englischkenntnissen hapert’s. „Beispiel“ heißt auf englisch „example“. Vielleicht clickst du mal auf den derart beschrifteten Reiter …

              Ach, das ist mir ja noch garnicht aufgefallen[/ironie].
              Ist dort ein Beispiel, dass in die oben genannte Kategorie passt?

              Grüße, CL

              --
              ie:{ fl:) br:^ va:) ls:~ fo:| rl:( n4:& ss:| de:> js:) ch:| sh:} mo:} zu:(
              1. @@CL:

                nuqneH

                Ach, das ist mir ja noch garnicht aufgefallen[/ironie].
                Ist dort ein Beispiel, dass in die oben genannte Kategorie passt?

                Sry, da hab ich mich verkuckt.

                Qapla'

                --
                Wer möchte nicht lieber durch Glück dümmer als durch Schaden klüger werden? (Salvador Dalí)
      2. Klingt nach komplizierter Materie, mit der ich mich wohl einige Zeit auseinandersetzen werde.

        Das sind eigentlich die Grundlagen funktionaler Programmierung. Obwohl JavaScript eine stark funktionale Programmiersprache ist, wird sie selten als solche wahrgenommen. Das Mischen von klassischen Schleifen und Closures/Callbacks ist da eigentlich eine Inkonsistenz.

        Meineswissens kann man im Callback von getJSON den Funktionen keine weiteren Parameter übergeben, ich bin mir allerdings nicht sicher.

        Falls das eine Frage ist, ich verstehe nicht, worauf du hinaus willst. Wem willst du was übergeben?

        Mathias

    2. Hi Matthias,

      Jedenfalls solltest du den Ajax-Request keinesfalls auf synchron umstellen.

      Magst Du erklären warum? Meinst Du das generell, bzw. wann ist ein synchroner Ajax-Aufruf sinnvoll?

      Gruß
      Stefanie

      PS: Ich bin gerade bei der Einarbeitung ins Thema javaScript/jQuery - Deine Webseite hat mir beim Verständnis schon sehr geholfen, vor allem die Umsetzung der Objektorientierung betreffend. Danke dafür!

      1. Hallo,

        Jedenfalls solltest du den Ajax-Request keinesfalls auf synchron umstellen.

        Magst Du erklären warum? Meinst Du das generell, bzw. wann ist ein synchroner Ajax-Aufruf sinnvoll?

        Ein synchroner Aufruf ist nie wünschenswert, denn er hält die JavaScript-Verarbeitung solange an, bis die Serverantwort eingetrudelt ist. Das kann kurz oder lange dauern, währenddessen sind keine parallel laufenden Scripte möglich. Dieses Verhalten ist für JavaScript sehr untypisch, daher kann sich die Website seltsam während eines synchronen Ajax-Requests verhalten. Im schlimmsten Fall ist das gesamte User-Interface eingefroren und reagiert nicht auf Eingaben.

        Durch die funktionale Natur von JavaScript und die Event-Loop (die Warteschlange, in der auszuführende Funktionen gestellt und nacheinander abgearbeitet werden) ist es möglich, sämtlichen Input und Output (I/O) in JavaScript asynchron zu verarbeiten. Deshalb sind fast alle wichtigen APIs zum Lesen und Schreiben asynchron, arbeiten also mit Callbacks bzw. Deferreds oder eventbasiert. Damit wird die weitere Ausführung von JavaScripten nicht geblockt, stattdessen kann die Event-Loop weitere anstehende Funktionsaufrufe abarbeiten.

        Dieses Prinzip von »Non-blocking I/O« ist die Grundlage von Node.js, eine Plattform für serverseitiges JavaScript. Sämtliche Festplatten-, Datenbank- und Netzwerkoperationen sind dort asynchron. Das macht die Programmierung oftmals kompliziert, ermöglicht aber eine einfache Parallelisierung und Skalierung vieler Aufgaben. Während der JavaScript-Interpreter im Browser meist nur die Eingaben eines Nutzers verarbeiten muss, muss Node.js gleichzeitig tausende Nutzer bedienen. Und das ist auch möglich, denn die meiste Zeit wartet der JavaScript-Code einer Webanwendung auf die Datenbankantwort, das Netzwerk o.ä.

        Mathias

        1. Guten Morgen!

          er hält die JavaScript-Verarbeitung solange an, bis die Serverantwort eingetrudelt ist. Das kann kurz oder lange dauern, währenddessen sind keine parallel laufenden Scripte möglich.

          Ach so, JavaScript ist keine multithreadingfähige Sprache - da muss ich Umdenken lernen. Allerdings sind ja manchmal während einer laufenden Verarbeitung auch gar keine User-Eingaben erwünscht (mein Anwendungsfall derzeit ist allerdings sowieso speziell, da ich keine "normalen" Webseiten, sondern quasi Benutzeroberflächen entwickle).

          Das macht die Programmierung oftmals kompliziert,

          Das stimmt... Vor allem, die Software dabei auch noch übersichtlich und verständlich zu halten.
          Wie gestaltest Du üblicherweise die Verarbeitung, wenn mehrere Werte für die weitere Verarbeitung notwendig sind? Vor den Requests rücksetzen, und in dem (gleichen) Callback nur weiter verarbeiten, wenn alle Werte inzwischen angekommen sind?

          Gruß und Danke
          Stefanie