2009-01-14 7 views
9

Ich habe ein Stück von jQuery-Code, der mehrere getJSON() Anrufe in schneller Folge ruft:jQuery Umfang oder Race-Bedingung in AJAX/getJSON

var table = $("table#output"); 
for (var i in items) { 
    var thisItem = items[i]; 
    $.getJSON("myService", { "itemID": thisItem }, function(json) { 
     var str = "<tr>"; 
     str += "<td>" + thisItem + "</td>"; 
     str += "<td>" + json.someMember + "</td>"; 
     str += "</tr>"; 
     table.append(str); 
    }); 
} 

Wenn ich laufen diese gegen einen laggy Server, der Tisch mit den bevölkerten wird erwartet json.someMember Werte (sie kommen außerhalb der Reihenfolge: das stört mich nicht), aber die thisItem Spalte ist mit einer unvorhersehbaren Mischung von Werten aus verschiedenen Iterationen bestückt.

Ich gehe davon aus, dass dies etwas mit Umfang und Timing zu tun hat - die Callback-Funktion liest thisItem aus einem größeren Bereich? Habe ich recht? Wie verhindere ich das?

Meine aktuelle Problemumgehung ist, dass der JSON-Dienst eine Kopie seiner Eingaben zurückgibt - was zumindest nicht zufriedenstellend ist.

+0

Danke Slim für das Stellen dieser Frage. Ich hatte auch einige Probleme (ich wusste, dass die asynchrone Funktion zurückkehrt, aber nicht sicher ist, wie man den getJSON-Aufruf zurücksendet, an welcher Stelle ein Rückgabewert platziert werden soll). –

Antwort

12

Scheint wegen der Schleife wie ein Problem mit dem Umfang zu sein. Versuchen Sie folgendes:

var table = $("table#output"); 
for (var i in items) { 
    var thisItem = items[i]; 
    $.getJSON("myService", { "itemID": thisItem }, (function(thisItem) { 
     return function(json) { 
      var str = "<tr>"; 
      str += "<td>" + thisItem + "</td>"; 
      str += "<td>" + json.someMember + "</td>"; 
      str += "</tr>"; 
      table.append(str); 
     } 
    })(thisItem)); 
} 

bearbeiten: alles, was ich tat, war Umfang thisItem zum $.getJSON Rückruf.

+0

Ich glaube nicht, dass dies mit jQuery funktionieren würde. Würde der JSON nicht anstelle der thisItem Variable in den Closy gelangen und einen Fehler verursachen? – jacobangel

+1

Nr. $ .getJSON wird die innere Funktion übergeben; derjenige, der den Parameter "json" erhält. –

+0

Scheint ein Leckerli (nachdem ich alle Klammern sortiert bekommen habe) gearbeitet zu haben. Vielen Dank! – slim

3

Javascript verwendet keinen Block für den Bereich. Scope basiert nur auf Funktionen.

Wenn Sie einen neuen Bereich möchten, müssen Sie eine neue interne Funktion deklarieren und sofort ausführen, dies ist die einzige Möglichkeit, einen neuen Bereich in Javascript zu erstellen.

var table = $("table#output"); 
for(var i in items) 
{ 
    (function(){ 
     var thisItem = items[i]; 
     $.getJSON("myService", { "itemID": thisItem }, function(json) 
     { 
      var str = "<tr>"; 
      str += "<td>" + thisItem + "</td>"; 
      str += "<td>" + json.someMember + "</td>"; 
      str += "</tr>"; 
      table.append(str); 
     }); 
    })(); 
} 
+0

Ich mag diese Lösung, da es mir erlaubt, mehr lokale Variablen wie thisItem zu haben, ohne eine ausführliche Funktionssignatur. – slim

+0

Spaß Tatsache: das ist, wie Scoping ist in der Regel implementiert in Schema – Javier

+0

Ich vergaß einen anderen Weg, könnten Sie eine for-Schleife aus einer Bibliothek, diese tatsächlich nehmen eine Funktion als der Block bei jeder Iteration auszuführen. In jQuery: $ .each (Elemente, Funktion (i, Element) {...}); –