2009-01-14 7 views
9

Mam kawałek kodu jQuery, który wywołuje kilka getJSON() połączeń w krótkim odstępie czasu:jQuery zakres lub rasę warunek w 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); 
    }); 
} 

Gdy uruchomię to na serwerze laggy, tabela zostanie wypełniona Oczekiwano wartości json.someMember (przybywają one poza kolejnością: nie mam nic przeciwko temu), ale kolumna thisItem jest zapełniona nieprzewidywalną mieszanką wartości z różnych iteracji.

Zakładam, że ma to jakiś związek z zakresem i czasem - funkcja oddzwaniania czyta thisItem z szerszego zakresu? Czy mam rację? Jak mogę temu zapobiec?

Moje bieżące obejście polega na tym, że usługa JSON zwraca kopię swoich danych wejściowych - co najmniej nie jest satysfakcjonujące.

+0

Dzięki Slim za zadanie tego pytania. Miałem również pewne problemy (wiedziałem o powrocie funkcji asynchronicznej, ale nie wiem, jak zasygnalizować wywołania getJSON, jaką lokalizację umieścić wartość zwracaną). –

Odpowiedz

12

Wygląda na to, że problem spowodował pętlę. Spróbuj tego:

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)); 
} 

Edycja: wszystko zrobiłem było zakres thisItem do $.getJSON zwrotnego.

+0

Nie sądzę, aby to działało z jQuery. Czy json nie zakończyłby się przejściem do zamknięcia zamiast zmiennej thisItem i spowodowałby błąd? – jacobangel

+1

Nr .getJSON zostaje przekazany funkcji wewnętrznej; ten, który otrzymuje parametr "json". –

+0

Wydaje się, że działał uczta (po tym, jak wszystkie aparaty zostały posortowane!). Dzięki! – slim

3

Javascript nie używa bloku do zakresu. Zakres jest oparty tylko na funkcjach.

Jeśli chcesz nowego zakresu, musisz zadeklarować nową funkcję wewnętrzną i uruchomić go natychmiast, jest to jedyny sposób, aby utworzyć nowy zakres w JavaScript.

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

Podoba mi się to rozwiązanie, ponieważ pozwala mi mieć więcej zmiennych lokalnych, takich jak thisItem, bez podpisu funkcji verbose. – slim

+0

zabawny fakt: w ten sposób scopowanie jest zwykle implementowane na Schemacie – Javier

+0

Zapomniałem w inny sposób, można użyć pętli for z biblioteki, w rzeczywistości przyjmują one funkcję jako blok do wykonania w każdej iteracji. W jQuery: $ .each (items, function (i, item) {...}); –