2009-04-02 12 views
33

Mam aplikację, którą piszę, która modyfikuje dane na buforowanym obiekcie na serwerze. Modyfikacje są wykonywane przez wywołanie ajax, które zasadniczo aktualizuje właściwości tego obiektu. Kiedy użytkownik skończył działać, mam podstawowy przycisk "Zapisz zmiany", który pozwala mu zapisać dane i opróżnić buforowany obiekt.jQuery Ajax call - Ustaw wartość zmiennej na sukces

Aby chronić użytkownika, chcę je ostrzec, jeśli spróbuję odejść od strony, gdy zostały wprowadzone modyfikacje obiektu serwera, jeśli nie zostały zapisane. Stworzyłem więc metodę usługi WWW o nazwie IsInitialized, która zwróci wartość true lub false w zależności od tego, czy zmiany zostały zapisane, czy też nie. Jeśli nie zostały zapisane, chcę poprosić użytkownika i dać mu szansę na anulowanie żądania nawigacji.

Oto mój problem - mimo że mam poprawnie działające połączenia, nie mogę uzyskać wywołania sukcesu ajax, aby ustawić wartość zmiennej na jego funkcji wywołania zwrotnego. Oto kod, który mam teraz.

////Catches the users to keep them from navigation off the page w/o saved changes... 
window.onbeforeunload = CheckSaveStatus; 
var IsInitialized; 

function CheckSaveStatus() { 

    var temp = $.ajax({ 
     type: "POST", 
     url: "URL.asmx/CheckIfInstanceIsInitilized", 
     data: "{}", 
     contentType: "application/json; charset=utf-8", 
     dataType: "json", 
     success: function(result) { 
      IsInitialized = result.d; 
     }, 
     error: function(xmlHttpRequest, status, err) { 
      alert(xmlHttpRequest.statusText + " " + xmlHttpRequest.status + " : " + xmlHttpRequest.responseText); 
     } 

    }); 

    if (IsInitialized) { 
     return "You currently have unprocessed changes for this Simulation."; 
    } 
} 

Czuję, że mogę próbować użyć odwołania odsyłającego Success w niewłaściwy sposób. Jak ustawić zmienną javascript w oddzwanianiu Success, aby można było zdecydować, czy użytkownik powinien zostać wyświetlony w niezapisanym komunikacie zmian?

Jak już wskazano, wykonuję wywołanie asynchroniczne, co oznacza, że ​​reszta kodu jest wywoływana, zanim moja metoda zwróci. Czy istnieje sposób, aby użyć tego wywołania ajax, ale nadal złapać zdarzenia window.onunload? (bez tworzenia zsynchronizowanego ajaxu)

+0

Właśnie dostałem e-mail mówiąc, że to kwestia kopalni od 5 lat przeszłości był „oznaczony jako duplikat”. Pytanie "oryginalne" ma zaledwie rok. Maszyny do pracy w go-go! :) Jest to bardziej dogłębna odpowiedź. – Nathan

Odpowiedz

32

Ponieważ zachodzi taka potrzeba w zdarzeniu zwolnienia, konieczne będzie wykonanie połączenia synchronicznego. Może jednak zablokować okno przeglądarki/kartę w zależności od czasu trwania połączenia, ale ponieważ skutecznie uniemożliwiasz użytkownikowi zamknięcie okna ...

Dodaj async: false do swojego JSON, aby wykonać połączenie synchroniczne .

4

Chodzi o to, że żądanie wywołania Ajax jest asynchroniczne. Tak więc do czasu, kiedy sprawdzasz IsInitialized, połączenie jeszcze się nie zakończyło.

Proponuję określić swoje zachowanie w funkcji sukcesu.

Zasadniczo połączenie synchroniczne z ajaxem jest, jeśli nie niemożliwe, od prawdziwego zniechęcenia.

+0

Jakieś sugestie, w jaki sposób mogę nadal wychwytywać zdarzenie window.onbeforeunload przy użyciu wywołania asynchronicznego? – Nathan

2

Teoretycznie możesz zabić zdarzenie (return false) i zamknąć okno z sukcesem, ale myślę, że wpadłbyś w ograniczenia JavaScript określone przez niektórych użytkowników, a także po prostu pomyliłbyś się, dlaczego ich okno się nie zamyka. Tak więc, zgadzam się z Pawłem Krakowiakiem, samo wezwanie ajaxowe musi być synchroniczne.

Dodam, że będziesz chciał dać użytkownikowi powiadomienie, że sprawdzasz status (nie wyskakujące okienko, proszę, jeden z tych ładnych banerów powiadomień u góry okna) i pamiętaj, aby ustawić Opcja "timeout" $ .ajax na coś bardziej sensownego dla tej sytuacji, więc nie czekają wiecznie na zamknięcie okna.

+0

+1, uzgodnione w powiadomieniu. Słuszna uwaga. –

1

Wygląda na to, że najlepszym podejściem dla mnie było użycie opcji async: false w moim wywołaniu ajax. Chociaż rozumiem wahanie Rashacka w tej sprawie, uważam, że sytuacja ta uzasadnia środki.

Świetny punkt od Jerpha na temat upewnienia się, że nie pozostawiam użytkownika wiszącego podczas próby zweryfikowania jego statusu. Ta sprzężona opcja timeout jest ważna.

Dziękuję wszystkim, którzy skomentowali.

2

miałem podobny problem z próby ustawienia właściwości dla obiektu danych za pośrednictwem wywołania zwrotnego sukcesu ajax żądanie. Używanie async: false również nie rozwiązało mojego problemu. Co skończyło się robi było użyć setTimeout połączenia poza wywołania ajax i ustawić wartość limitu czasu do 1, tak jak poniżej:

function getSessionid() { 
    $.ajax({ 
     type: 'POST', 
     url: 'getSession.php', 
     dataType: 'text', 
     success: function(result){myData.sessionid = result;}, 
     error: function(data) {alert("Error!\n" + data);} 
    }); 
    setTimeout(function() {alert('sessionid = ' + myData.sessionid);},1); 
} 

Tylko o to opóźnienie 1 milisekundę wykonane wszystkie różnica w świecie. Bez niego właściwość sessionid nie byłaby ustawiona poza wywołaniem ajax, chociaż alerty w wywołaniu zwrotnym pokazały, że rzeczywiście została ustawiona. Jest to coś, o czym warto pomyśleć, jeśli napotkasz podobny problem.

Powiązane problemy