Menu Zamknij

Sleep w JavaScript

Ustawianie opóźnień w skryptach Javy nie jest takie oczywiste…

Z języków programowania chciałoby się użyć funckji sleep(int miliseconds); która zatrzyma CPU na jakiś czas – wiadomo, że jest to nieeleganckie, ale skuteczne. Jednak w przypadku stron WWW przykładowa implementacja

function sleep(milliseconds) {
  var start = new Date().getTime();
  while (true)
    if ((new Date().getTime() - start) > milliseconds)
      break;
}

naprawdę zawiesza procesor – nie jest to znane z C# System.Threading.Thread.Sleep(100) – więc wskazujące, że zawieszamy wątek, ale zawieszamy cały interpreter JS co równoznaczen jest z tym, że aktualizacje DOM czy po prostu tego co widzi użytkownik są niewidoczne. Ponadto monolity takie jak Mozilla Firefox zawisną w całej okazałości, czym może zainteresować się Windows – w skrajnej konfiguracji sam ubije nieodpowiadający proces. Przykład:

document.write("1 
"); sleep(1000); document.write("2
"); sleep(1000); document.write("3
"); sleep(1000); document.write("4
"); sleep(1000);

Wykonanie zawiesi wszystko i dumnie ukaże nam po ok. 4 sekundach 1-2-3-4, a nie po kolei tak jakbyśmy chcieli.

Przejdźmy do jedynego słusznego rozwiązania , tj. setTimeout

setTimeout(function() { coś(); }, 1000); 

Wszystko pięknie, ale sposób w jaki to zostanie zinterpretowane jest zaskakujący jak na trochę prymitywny względem wysokopoziomowców JavaScript. Otóż setTimeout znaczy to co znaczyć powinno tj. „zarejestruj event/przerwwanie, że za tyle milisekund wywołasz coś();, ale bez czekania tych milisekund wykonaj kolejną linię kodu”, a nie „odczekaj i wykona coś(); dopiero wtedy następną linię”. Oznacza to, że kod

setTimeout(function() {document.write('1 
'); }, 1000); setTimeout(function() {document.write('2
'); }, 1000); setTimeout(function() {document.write('3
'); }, 1000); setTimeout(function() {document.write('4
'); }, 1000);

odczeka sekundę i wypluje wszystko na raz!

Właściwe rozwiązanie to kolejne setTimeout’y większe od poprzednich:

setTimeout(function() {document.write('1 
'); }, 1000); setTimeout(function() {document.write('2
'); }, 2000); setTimeout(function() {document.write('3
'); }, 3000); setTimeout(function() {document.write('4
'); }, 4000);

Dodaj komentarz