Dlaczego funkcja setInterval() wykonuje się tylko raz a nie w kółko

0

Dopiero zaczynam naukę Javascript za pomocą tej książki http://helion.pl/ksiazki/javascript-dla-programistow-php-stoyan-stefanov,javphp.htm i mam problem. Napisałem zegar na stronę i chcę, aby on się aktualizował co 1 sekundę. Wszystko jest fajnie - moje dwie funkcje działają - ale setInterval() wykonuje się raz a nie w kółko. Gdzie jest błąd?

Oto kod

<script>
			var data,rok,miesiac,numerMiesiaca,numerTygodnia,dzienTygodnia,dzien,godzina,minuta,sekunda;
			
			function date() {
				data=new Date();
				rok=data.getFullYear();
				numerMiesiaca=data.getMonth();
				dzien=data.getDate();
				numerTygodnia=data.getDay();
				godzina=data.getHours();
				minuta=data.getMinutes();
				sekunda=data.getSeconds();
				
				switch(numerMiesiaca) {
					case 0: miesiac="styczeń"; break;
					case 1: miesiac="luty"; break;
					case 2: miesiac="marzec"; break;
					case 3: miesiac="kwiecień"; break;
					case 4: miesiac="maj"; break;
					case 5: miesiac="czerwiec"; break;
					case 6: miesiac="lipiec"; break;
					case 7: miesiac="sierpień"; break;
					case 8: miesiac="wrzesień"; break;
					case 9: miesiac="październik"; break;
					case 10: miesiac="listopad"; break;
					case 11: miesiac="grudzień"; break;
				}

				switch(numerTygodnia) {
					case 0: dzienTygodnia="niedziela"; break;
					case 1: dzienTygodnia="poniedziałek"; break;
					case 2: dzienTygodnia="wtorek"; break;
					case 3: dzienTygodnia="środa"; break;
					case 4: dzienTygodnia="czwartek"; break;
					case 5: dzienTygodnia="piątek"; break;
					case 6: dzienTygodnia="sobota"; break;
				}
				
				if(dzien<10) {
					dzien="0"+dzien;
				}
				if(godzina<10) {
					godzina="0"+godzina;
				}
				if(minuta<10) {
					minuta="0"+minuta;
				}				
				if(sekunda<10) {
					sekunda="0"+sekunda;
				}
				document.write("Atualny czas:<br/>"+dzienTygodnia+"<br/>"+dzien+" "+miesiac+" "+rok+"<br/>godz. "+godzina+":"+minuta+":"+sekunda);
			}
			
			function aktualnaData() {
				window.setInterval(date(), 1000);
			}
		</script>

A to wywołanie

<script>
      aktualnaData();
</script>
0

Myślę że funkcja Ci się wykonuje jak najbardziej tylko nie podmieniasz żadnego teksu w html. Spróbuj zrobić tak:

function date() {
...
t="Atualny czas:<br/>"+dzienTygodnia+"<br/>"+dzien+" "+miesiac+" "+rok+"<br/>godz. "+godzina+":"+minuta+":"+sekunda;
document.getElementById("time").innerHTML = t;
}
function aktualnaData() {
    setInterval(function(){date();}, 1000);
}
aktualnaData();

i w html dodaj np. div'a

<div id='time'></div>

JSBin: http://bit.ly/1o4drtd

0

Wielkie dzięki

3

Błąd jest w argumencie setInterval. Jako pierwszy argument podajesz tam metodę, a nie wartość przez nią zwracaną.

  1. setInterval(date(), 1000); - wywołaj co sekundę to, co w argumencie, czyli to, co zwróci date(), czyli wywołaj raz date(), żeby poznać wartość tego czegoś, a potem wysyp się, bo funkcja zwróciła void, czyli jest to identyczne z wywołaniem date(); setInterval(void, 1000);.
  2. setInterval(date, 1000); - wywołaj co sekundę to, co w argumencie, czyli date() (a nie to, co zwróci date()).
  3. setInterval(function() { date(); }, 1000); - wywołaj co sekundę to, co w argumencie, czyli wywołaj funkcję anonimową, która wywoła funkcję date(). W zasadzie tożsame z drugim sposobem, tylko właściwa metoda jest niepotrzebnie zagnieżdżana.
  4. function dateContainer() { return function() { date() }; } setInterval(dateContainer(), 1000); - wywołaj co sekundę to, co zwróci funkcja dateContainer(). Funkcja dateContainer() zwróci funkcję wywołującą date(), więc wszystko zadziała.
  5. function dateContainer() { return date; } setInterval(dateContainer(), 1000); - wywołaj co sekundę to, co zwróci funkcja dateContainer(). Funkcja dateContainer() zwróci funkcję date (nie wynik działania funkcji, tylko funkcję!), więc wszystko zadziała. Zasada identyczna jak w 3.
  6. function dateContainer() { return date(); } setInterval(dateContainer(), 1000); - to samo co w 1 - wywołaj dateContainer(), która zwróci wynik działania funkcji date(), a ponieważ date() zwraca void, to dateContainer() też zwróci void, a to oznacza wywołanie setInterval(void, 1000), czyli kod nie zadziała.

[edit]
document.write() jest przestarzałe i działa tylko do momentu, kiedy dokument jest jeszcze generowany (czyli zanim parser dotrze do końca dokumentu). Jakiekolwiek setTimeout czy setInterval nie zadziała z taką funkcją, bo jej wywołanie odbędzie się już PO zamknięciu dokumentu.

0

Ogromnie dziękuję

0

Czy z powodu http://lekka.cba.pl/htm_java/js_innerHTML_or_appendChild.htm nie lepiej stosować taki kod

var data,rok,miesiac,numerMiesiaca,numerTygodnia,dzienTygodnia,dzien,godzina,minuta,sekunda,miliSekunda,czas,element,tekst1,tekst2,tekst3,text4,nowaLinia,pierwszy=true;

function date() {
	data=new Date();
	rok=data.getFullYear();
	numerMiesiaca=data.getMonth();
	dzien=data.getDate();
	numerTygodnia=data.getDay();
	godzina=data.getHours();
	minuta=data.getMinutes();
	sekunda=data.getSeconds();
	miliSekunda=data.getMilliseconds();
	
	switch(numerMiesiaca) {
		case 0: miesiac="styczeń"; break;
		case 1: miesiac="luty"; break;
		case 2: miesiac="marzec"; break;
		case 3: miesiac="kwiecień"; break;
		case 4: miesiac="maj"; break;
		case 5: miesiac="czerwiec"; break;
		case 6: miesiac="lipiec"; break;
		case 7: miesiac="sierpień"; break;
		case 8: miesiac="wrzesień"; break;
		case 9: miesiac="październik"; break;
		case 10: miesiac="listopad"; break;
		case 11: miesiac="grudzień"; break;
	}

	switch(numerTygodnia) {
		case 0: dzienTygodnia="niedziela"; break;
		case 1: dzienTygodnia="poniedziałek"; break;
		case 2: dzienTygodnia="wtorek"; break;
		case 3: dzienTygodnia="środa"; break;
		case 4: dzienTygodnia="czwartek"; break;
		case 5: dzienTygodnia="piątek"; break;
		case 6: dzienTygodnia="sobota"; break;
	}
	
	if(dzien<10) {
		dzien="0"+dzien;
	}

	if(godzina<10) {
		godzina="0"+godzina;
	}

	if(minuta<10) {
		minuta="0"+minuta;
	}				

	if(sekunda<10) {
		sekunda="0"+sekunda;
	}
	
	if(miliSekunda<10) {
		miliSekunda="00"+ miliSekunda;
	}
	else if(miliSekunda<100) {
		miliSekunda="0"+ miliSekunda;
	}
	
	element=document.getElementById('aktualnyCzas');
	if(pierwszy===true) {
		tekst1=document.createTextNode("Atualny czas:");
		element.appendChild(tekst1);
		nowaLinia=document.createElement("br");
		element.appendChild(nowaLinia);
		tekst2=document.createTextNode(dzienTygodnia);
		element.appendChild(tekst2);
		nowaLinia=document.createElement("br");
		element.appendChild(nowaLinia);
		tekst3=document.createTextNode(dzien+" "+miesiac+" "+rok);
		element.appendChild(tekst3);
		nowaLinia=document.createElement("br");
		element.appendChild(nowaLinia);
		tekst4=document.createTextNode("godz. "+godzina+":"+minuta+":"+sekunda+":"+miliSekunda);
		element.appendChild(tekst4);
	}
	else {
		tekst2.nodeValue=dzienTygodnia;
		tekst3.nodeValue=dzien+" "+miesiac+" "+rok;
		tekst4.nodeValue="godz. "+godzina+":"+minuta+":"+sekunda+":"+miliSekunda;
	}
	pierwszy=false;
}

function aktualnaData() {
	window.setInterval(date, 1);
}
aktualnaData();
0

Być może, gdybyś pisał coś, gdzie by to miało znaczenie. Ale w tym przypadku jedynie co osiągasz poprzez createTextNode/appendChild to gorszy(brzydszy) kod, więc w tym wypadku lepiej wypada innerHTML. Warto wiedzieć o takich rzeczach, ale nie stosować ich bez przemyślenia.

0

Dziękuję za wyjaśnienie

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