2012-06-10 11 views
15

Występuje problem z funkcją $ .get. URL zawiera jsonSpraw, aby funkcja "get" AJAX była synchroniczna/jak uzyskać wynik?

mój kod:

xyz = null 

    $.get('http://www.someurl.com/123=json', function(data) { 
     var xyz = data.positions[0].latitude; 
    }); 

alert(xyz); 
//some more code using xyz variable 

wiem że xyz ostrzeże zerowy wynik, ponieważ $.get jest asynchroniczny.

Czy istnieje sposób, w jaki mogę użyć funkcji xyz poza tą funkcją get?

+0

Po przeniesieniu słowa kluczowego 'var' z funkcja i przed początkowym 'xyz', możesz użyć go w dowolnym miejscu w tym zakresie w dowolnej funkcji, która wykonuje się po zakończeniu żądania ajax. – Paulpro

+4

Chociaż * jest * ** synchroniczne ** AJAX (jest to * udokumentowane * w jQuery), zwykle należy * tego unikać * z powodu negatywnego wpływu, jaki ma na wrażenia użytkownika. Zamiast tego skoncentruj się na wykorzystaniu modelu asynchronicznego AJAX opartego na zdarzeniach. Oznacza to, że zaktualizuj DOM za pomocą 'xyz' * od wewnątrz * wywołania zwrotnego. –

+0

@ pst. To samo pytanie przez cały czas. Ten i problem z DOM. – gdoron

Odpowiedz

7

Prawdziwa odpowiedź jest NO, ale można użyć to:

function useXYZ(){ 
    alert(xyz); 
} 

xyz = null   

$.get('http://www.someurl.com/123=json', function(data) { 
    xyz = data.positions[0].latitude; 
    useXYZ(); 
}); 
+0

Po co marnować czas i chaos na globalną własność? (Lub zamknięta zmienna). Często jest lepiej napisane jako 'function useXYZ (xyz) {..}' ... a następnie przechodzą przez dane z wywołania zwrotnego. –

+0

@ pst. Myślałem, że to zrobię, ale chciałem mu pokazać, jak może wykorzystać zmienną zewnętrzną. (BTW, nie musi to być zmienna globalna). Możesz edytować, jak chcesz, proszę pana! – gdoron

+0

Dzięki! Pomyślałem, że działa dobrze z alarmem. Nadal mam problem z resztą scenariusza. I faktycznie, kiedy muszę włożyć wiele rzeczy do funkcji useXYZ() {...} – Diolor

22

get jest skrót. Można zrobić to samo, ale synchronicznie, używając:

var xyz = null 


$.ajax({ url: 'http://www.someurl.com/123=json', 
     async: false, 
     dataType: 'json', 
     success: function(data) { 
       xyz = data.positions[0].latitude; 
      } 
     }); 


alert(xyz); 

Musisz zadeklarować zmienną xyz przed wywołaniem ajax, choć.

+0

Cóż, szczerze mówiąc moja początkowa odpowiedź była kiepska. Naprawdę powinienem przestać próbować odpowiadać na pytania z mojego telefonu. – HackedByChinese

+0

W Chrome i Firefox wciąż otrzymuję zero. W safari działa dobrze – Diolor

+0

Hmm. Testowałem w Safari, Chrome i Firefox (w systemie OS X). Oto czysty przykład http://jsfiddle.net/HackedByChinese/F2Ey5/1/ – HackedByChinese

4

Jest to częsty problem z Javascriptem. Kod JavaScript musi być napisany w stylu przekazywania kontynuacji. To jest denerwujące, ale jest czymś, co można przekonwertować bez myślenia za dużo.

basicaly, gdy chcemy mieć coś podobnego

var x = someSyncFunction(a, b, c); 
//do something with x 
console.log(x); 

Możemy przekształcić go w kodzie asynchronicznej poprzez cały kod po funkcja zwraca do funkcji kontynuacji i obracając x ze zmiennej do parametru ciągłe oddzwanianie.

someAsyncFunction(a, b, c, function(x){ 
    //do something with x; 
    console.log(x); 
}); 

Należy pamiętać, że bardzo łatwo jest napisać mylący kod. Dobrą sztuczką, o której należy pamiętać, jest to, że możesz sprawić, że twoje własne funkcje będą również odbierane. To pozwala im być używany przez inną funkcję (tak jak normalne funkcje synchronizacji pomocniczych, które zwracają wartość mogą być wykorzystane przez różne funkcje)

var getXyz = function(onResult){ //async functions that return do so via callbacks 
           //you can also another callback for errors (kind of analogous to throw) 
    $.get('http://www.someurl.com/123=json', function(data) { 
     var xyz = data.positions[0].latitude; 
     onResult(xyz); //instead of writing "return xyz", we pass x to the callback explicitely. 
    }); 
}; 

getXyz(function(xyz){ //this would look like "var xyz = getXyz();" if it were sync code instead. 
    console.log('got xyz'); 
}); 

Sztuką jest, aby zmienić wszystkie wypowiedzi powrocie z funkcji do wywołania funkcji funkcja zwrotna. Wydaje się, że funkcja async nigdy nie została zwrócona, a jedynym sposobem, aby zwrócić wartość komuś, jest przekazanie tej wartości do wywołania zwrotnego.

Możesz zapytać, dlaczego nie ma prostszego sposobu na zrobienie tego wszystkiego. No cóż, nie ma, chyba że używasz innego języka zamiast Javascript (lub przynajmniej czegoś, co pozwala pisać kod asynchroniczny w stylu synchronicznym, ale automatycznie kompiluje się do zwykłego Javascript)

+0

Dzięki! Co się stanie, jeśli będę musiał pobrać dwie partie z JSON jak "xyz" dla szerokości i "abc" dla długości? W jaki sposób będzie on i funkcja onResult (xyz). Czy mogę zagnieździć je w środku, czy też mam utworzyć drugą funkcję (abc)? – Diolor

+0

Można spakować obie wartości wewnątrz jednego obiektu i przekazać obiekt do wywołania zwrotnego 'onResult ({lat: xyz, long: abc});', podobnie jak zwróciłbyś wiele wartości z funkcji synchronicznej) lub mógłbyś funkcja wywołania zwrotnego otrzymuje dwa parametry zamiast jednego 'onResult (xyz, abc);'. Posiadanie więcej niż jednego wywołania zwrotnego jest zwykle związane z różnymi i wzajemnie wykluczającymi się ścieżkami obliczeniowymi. Typowym przykładem jest wywołanie zwrotne sukcesu (lub "powrót") i jedno wywołanie błędu (lub "odrzucenie"). – hugomg

Powiązane problemy