$.ajax w setInterval i problem z asynchronicznością

0

Cześć Wam
Dzisiaj pisałem sobie prosty skrypt w JS którego zadaniem było odświeżanie treści na stronie co jakiś określony czas.
Skorzystałem z setInerval i $.ajax jako z najprostszego rozwiązania i ... pojawił się problem.

 setInterval(function() {
		$.ajax({
			url: baseUrl + 'other/getData',
			success: function(data) {
				data = JSON.parse(data);
				console.log(data);
			},
			async: false // <- TUTAJ JEST PROBLEM
		});
	}, 3000);

AJAXowe wywołanie nic sobie nie robiło z ustawionego interwału czasowego i wykonywało się cały czas. Dopiero po zmianie async z false na true (ew. usunięciu tej linijki bo true jest domyślne) wszystko zaczęło sprawnie działać.
Czy ktoś mógłby mi wyjaśnić, z czystej ciekawości, dlaczego wyłączenie asynchroniczności powoduje pominięcie interwału czasowego?

Pozdrawiam

0

Po pierwsze:

Basically, using setInterval with async code is not the best way to go. It's better to use setTimeout to schedule a new request once the previous one has finished.

Po drugie jak to nic sobie nie robiło? Oczywiście, że robiło. Co 3 sekundy zlecałeś do wykonania kolejne synchroniczne żądanie.

let then = performance.now();
setInterval(function() {
    const now = performance.now();
    console.log("Delta = " + (now - then) + " milliseconds.") // będziesz dostawał pi razy drzwi 3000
    then = now;
    $.ajax({
        url: 'https://jsonplaceholder.typicode.com/posts/1',
        success: function(data) {
            console.log('done');
            console.log(data);
        },
        async: false // <- TUTAJ JEST PROBLEM
    });
}, 3000);
0

Cóż, zgadzam się, że wykonywanie asynchronicznego kodu w setInterval nie jest może najmądrzejszym rozwiązaniem bo oczywiście wcześniejsze wykonanie może jeszcze się nie skończyć kiedy zaczynane jest następne i setTimeout w takim przypadku będzie lepsze bo nie doprowadzi do takiego rozwoju zdarzeń ale myślę, że nie przeczytałeś dokładnie tego co napisałem ;).
Domyślnie chciałem, żeby AJAXowe odwołanie działało synchronicznie a więc nic nie stoi na przeszkodzie umieszczenia go w setInterval czyż nie? Niestety przez błąd nad którego naturą się zastanawiam nie było to możliwe i użyłem asynchronicznego odwołania ale to właśnie po to założyłem ten temat.
Uruchomiłem sobie Twój kod i cóż nie jest to "pi razy drzwi 3000" tylko 900 ;). Przy async na false. Jeśli natomiast ustawie na true - działa.
I właśnie to mnie zastanawia. I to właśnie odpowiedzi na to szukam - dlaczego.

screenshot-20170109201519.png

Pozdrawiam

0

Ciekawi mnie jak osiągasz swoje wyniki. Wrzuć to może na jakiegoś JSFiddle.

async: false blokuje wykonanie jakiegokolwiek kodu. Jeżeli zrobimy coś takiego:

let then = performance.now();
setInterval(function() {
    const now = performance.now();
    console.log("Delta = " + (now - then) + " milliseconds.")
    then = now;
    $.ajax({
        url: 'https://jsonplaceholder.typicode.com/posts/1',
        success: function(data) {
            console.log('done');
        },
        async: false
    });
}, 1); // <--- zwróć uwagę, że interwał to 1ms

To będziemy dostawali Delta = x, gdzie x to +- czas wykonania synchronicznego żądania. Mimo to, że setInterval powinien wykonywac kod nie wcześniej niż co 1 ms, to ponieważ jest asyc: false to wszystko jest wstrzymane i kolejny interwał wykona się tak szybko jak to możliwe, czyli po odblokowaniu przeglądarki (gdy wykona się żądanie).

W twoim przypadku nie masz 1 ms, tylko 3000 ms = 3 sek. Dlatego dziwi mnie Twój output, bo żeby to się rozjechało Twoje żądanie musiało by trwać powyżej 3 sekund, ale wtedy byś dostawał delty również powyżej 3 sekund - chyba że coź źle rozumuje. Możliwe, że u siebie w kodzie masz 300 zamiast 3000, to wtedy by miało sens, bo chcesz przy synchronicznym żadaniu mieć interwał 300 ms, ale żądanie trwa średnio > 800 ms, więc Twoje wyniki by miały jakiś sens.

Ciekawe to :)

0

No właśnie też mnie to zaciekawiło ;).
Nie, na pewno jest to 3000ms nie 300ms ale właśnie sprawdziłem to na kilku przeglądarkach bo do tej pory korzystałem sobie jedynie z Firefox Developer Edition i tam właśnie coś takiego się pojawia. Sprawdziłem natomiast na zwykłym Firefoksie i Chromie i rzeczywiście błąd nie występuje 8|. Sprawdź jak możesz czy u Ciebie na Developer Edition też zrobi się coś takiego. Zgłosiłem to do Mozilli jako bug, zobaczymy co mi odpowiedzą.

1 użytkowników online, w tym zalogowanych: 0, gości: 1