2010-02-03 10 views
5

Mam połączenie Ajax, które obecnie musi być synchroniczne. Jednak podczas wykonywania tego połączenia Ajax interfejs przeglądarki zawiesza się, aż do powrotu połączenia. W przypadku przekroczenia limitu czasu może to zablokować przeglądarkę pod kątem significant period of time.Czy można pobrać okno przeglądarki do aktualizacji w pętli Javascript?

Czy istnieje sposób na pobranie przeglądarki (dowolnej przeglądarki) w celu odświeżenia interfejsu użytkownika, ale nie można wykonać żadnego skryptu JavaScript? Najlepiej byłoby, gdyby niektóre polecenia, takie jak window.update(), pozwoliłyby na odświeżenie wątku interfejsu użytkownika.

Jeśli będzie to możliwe, to mogę wymienić synchroniczne wywołanie AJAX z czymś takim:

obj = do_async_ajax_call(); 
while (!obj.hasReturned()) { 
    window.update(); 
} 
// synchronous call can resume 

tego powodu, że nie mogę używać setTimeout lub wznowić funkcję w zwrotnego, jest to, że przepływ egzekucja nie może być przerwany (istnieje zbyt wiele zmiennych, że wszyscy są od siebie zależne, a przepływ long_function() przeciwnym razie muszą być wznowione jakoś):

function long_function() { 
    // lots of code, reads/writes variable 'a', 'b', ... 
    if (sync_call_is_true()) { 
    // lots of code, reads/writes variable 'a', 'b', ... 
    } else { 
    // lots of code, reads/writes variable 'a', 'b', ... 
    } 
    // lots of code, reads/writes variable 'a', 'b', ... 
    return calculated_value; 
} 
+2

Dlaczego połączenie musi być synchroniczne? –

+1

Czy możesz opublikować cały kod połączenia? Prawdopodobnie można to uprościć i korzystać z funkcji XHR, aby obsługiwać to, czego potrzebujesz (chyba, że ​​jQuery jest opcją, a nawet czystszym). Jeśli żadna z nich nie jest opcją, żądam zmiany nazwy funkcji na 'do_sync_jax_call();' –

Odpowiedz

3

Musisz wymienić synchroniczne żądania ze związkiem żądanie asynchroniczne i użyj wywołania zwrotnego. Uproszczony Przykładem może być:

obj = do_async_ajax_call(function (data, success) 
{ 
    if (success) 
    { 
     // continue... 
    } 
}); 

function do_async_ajax_call(callback) 
{ 
    var xhr = new XMLHttpRequest(); 
    xhr.open("GET", "http://mysite.com", true); 
    xhr.onreadystatechange = function() 
    { 
     if (xhr.readyState == 4 && xhr.status == 200) 
      callback(xhr.responseXML, true); 
     else if (xhr.readyState == 4) 
      callback(null, false); 
    } 
    xhr.send(); 
} 

ten sposób przekazujemy anonimową funkcję jako parametr do funkcji wzywającego Ajax. Gdy ajax jest zakończony, funkcja, która została przekazana, jest wywoływana z przekazanym do niej responseXML. W międzyczasie przeglądarka mogła zrobić to normalnie, dopóki połączenie nie zostanie zakończone. Z tego miejsca reszta kodu będzie kontynuowana.

+0

Zwykle byłoby to wystarczające, ale nie mogę podzielić przepływu operacji (zaktualizowanego w pytaniu). Próbuję teraz innego podejścia ... – jevon

+0

Jest * zawsze * możliwe podzielenie go; to jest transformacja CPS (spójrz na "styl przekazywania kontynuacji", parametr kontynuacji jest twoim oddzwanianiem). Twoje lokalne zmienne stanu są po prostu zamknięte w funkcji wywołania zwrotnego. Pętle stają się rekurencyjnymi połączeniami. To nie jest takie trudne ani niejasne, kiedy już to zrozumiesz. –

+0

Zgadzam się, że zawsze jest to możliwe, ale w tym przypadku nie było to najlepsze rozwiązanie (było zbyt wiele zmiennych stanu!) :) W końcu użyłem wyniku poprzednich oddzwonień (lub regularnego odpytywania serwera), aby zaktualizować klienta -side z buforowaną wartością wywołania synchronicznego, gdy jest to konieczne, więc nie musi w ogóle wywoływać Ajax. – jevon

0

wziąć resztę rozmowy i umieścić go w tym wywołaniu zwrotnym jest wywoływana, gdy wynik wraca. Poważnie wątpię, że byłoby to całkowicie niemożliwe. Wszelkie logika trzeba umieścić w zaproszeniu mogą być powielane w zwrotnego

0

asynchroniczny ajax pobrać następnie setTimeout i wykonać pracę przetwarzania w kawałkach (uruchamiane przez callback)

0

JavaScript to jeden wątek. Z definicji nie można aktualizować interfejsu użytkownika, gdy znajdujesz się w pętli odpływu. Jednak począwszy od Firefoksa 3.5 dodano obsługę wielowątkowych skryptów JavaScript zwanych pracownikami WWW. Pracownicy WWW nie mogą wpływać na interfejs użytkownika strony, ale nie będą również blokować aktualizacji interfejsu użytkownika. Nasi pracownicy są również obsługiwani przez Chrome i Safari.
Problem polega na tym, że nawet jeśli przeniesiesz swoje wywołanie AJAX do wątku w tle i oczekiwanie na wykonanie zostanie zakończone, użytkownicy będą mogli naciskać przyciski i zmieniać wartości w twoim interfejsie (i o ile rozumiem, to właśnie jesteś próbując uniknąć). Jedyne, co mogę zasugerować, aby uniemożliwić użytkownikom wprowadzanie jakichkolwiek zmian, to spinner, który zablokuje cały interfejs i nie pozwoli na żadną interakcję ze stroną, dopóki nie powróci połączenie internetowe.

+0

Nie mam nic przeciwko temu, że użytkownicy wchodzą w interakcję ze stroną (a interakcja jest w kolejce); ale obecnie, podczas gdy synchroniczne wywołanie Ajax jest wykonywane w przeglądarce Firefox, cała przeglądarka zawiesza się. Właśnie tego chcę zapobiec. – jevon

Powiązane problemy