webForumDet fria alternativet

Får felmeddelandet "To much recursion"

JavaScript

13 svar · 582 visningar · startad av vic

Medlem sedan apr. 2006244 inlägg
Frågan#1

Återigen ett problem när jag ska få något att rulla på i all evighet. Jag har ett script som med jämna mellarum ska hämta in ett antal divar med bilder via ajax. Jag har sen ett script som räknar hur många divar det finns och sedan sätter igång en tredje funktion som stänger av/sätter på divvarna (visibility:hidden/visibility:visible). Det fungerar hyffsat men efter ett tag så slutar det fungera och så får jag meddelandet "to much recursion"

Så här ser scripten ut, jag markera på vilken rad som felet till sist uppstår:

// Räknar ut hur många divar som finns och sätter därefter igång bildvisningen
function InitSpot()
	{
	var i = 1, elm, nr = 0;
	while (elm = d.getElementById("pic" + (i++)))
		{
		nr++;
		}
	
	Spot(nr); [red]// HÄR KOMMER FELMEDDELANDET EFTER ETT TAG[/red]
	}
	

// Visar bilderna efter varandra
function Spot(nr)
	{
	
	if(nr == 0)
		{
		InitSpot();	
		}
	
	var countdown = nr;
	var hide = countdown + 1;
	nr--;

	if(d.getElementById('pic'+hide))
		{
		d.getElementById('pic'+hide).style.visibility = 'hidden';
		}
			
	if(d.getElementById('pic'+countdown))
		{
		d.getElementById('pic'+countdown).style.visibility = 'visible';
		setTimeout("Spot(" +nr+ ")", 10000);
		}
		else
			{
			setTimeout("Spot(" +nr+ ")", 0);
			}
	}
	

function CountdownManager(period, times, action, tickNow){
	var action = action, period = period, times = times;

	function tick(){
		if(!--times)
			clearInterval(intId);
		
		action();
	}

	if ("undefined"!=typeof tickNow && tickNow)
		tick();

	if (times)
		var intId = setInterval(tick, period);
}

window.onload = function()
 {

	function LiveMess()
		{
		Ajax('ajax', 'livemess', 'livemess');	
		}
				

	function getSpot()
		{
		Ajax('ajax', 'spot', 'spot');	
		}
					
		new CountdownManager(60000, 60000, LiveMess);
		new CountdownManager(125000, 60000, getSpot);
				
		InitSpot();
 }

Skulle uppskatta lite hjälp på traven

Medlem sedan aug. 20003 575 inlägg
#2

Varför ökar du på nr med ett varje gång innan du anropar Spot(nr) där du genast minskar nr med ett?

Medlem sedan apr. 2006244 inlägg
#3

Ja, det kan jag inte förstå :) Riktigt meningslöst :) I vilket fall som helst är det inte där problemet ligger, har du några förslag?

Medlem sedan aug. 20003 575 inlägg
#4

okej, jag har en hypotes att koden nedanför triggas hela tiden, alltså att vilkoret nr == 0 är blir sant hela tiden och att då InitSpot(); anropas oändligt många gånger, kan det vara så?

	if(nr == 0)
		{
		InitSpot();	
		}
Medlem sedan apr. 2006244 inlägg
#5

Ne så är det ju inte, nr blir mindre hela tiden. När nr slutligen är noll aktiveras funktionen som kollar hur många nr (alltså divvar) som finns på sidan och sen börjar det hela om.

Jag märkte även att felmeddelandet löd "stack overlay error" i Internet Explorer medans Felmeddelandet i Mozilla är "To much recursion". Det verkar alltså som att nr förekommer för många gånger på något sätt. Kan man tömma/radera variabler i Javascript? Kan det kanske vara en lösning?

Medlem sedan juni 20031 837 inlägg
#6

Jag hade nog lag ut lite alert(nr) för att kontrollera att nr ändras hela tiden.
Du tar emot den som en parameter men returnerar aldrig den från funktionen.
Nu vet jag inte om javascript tar emot parametrarna som ett värde eller en referens.

Medlem sedan apr. 2006244 inlägg
#7

Grejen är ju att scriptet fungerar i typ 5 minuter, Hela köret rullar runt typ 20 varv, sedan lägger det av och så får jag de ovan beskrivna felmeddelanden.

Kan en funktion exekvera sig själv? I sådana fall skulle jag jag ju kunna köra

if(nr == 0)
 {
 Spot(getSpots());
 }

Och sedan låta getSpots returnera nr istället. Men skulle det verkligen lösa problemet? Jag tror jag ger upp nu och kör med iframe istället :)

Medlem sedan mars 20034 471 inlägg
#8

vic skrev:

Grejen är ju att scriptet fungerar i typ 5 minuter, Hela köret rullar runt typ 20 varv, sedan lägger det av och så får jag de ovan beskrivna felmeddelanden.

Hum? Når de här funktionerna någonsin ner till ett värde som inte kommer att anropa vidare någon annanstans? Så att du stänger "anropskön". Annars, om du hela tiden anropar funktioner om och om igen, kommer du för eller senare att ha käkat upp allt tillgängligt minne och då kraschar det just efter en stund. Exempel:

function knas1(nr) {
if (nr == 0)
  knas1(nr++);
else knas2(nr);
}

function knas2(nr){
  knas1(nr--);
}

knas1(3);

Ger anropskön:

knas1(3)
  knas2(3)
    knas1(2)
       knas2(2)
         knas1(1)
           knas2(1)
             knas1(0)
               knas1(1)
                 knas2(1)
                   knas1(0)
                     knas1(1)
                       knas2(1)
                          knas1(0)
                            ...

Inget av de tidigare funktionsanropen stängs eftersom de inte är klara förrän (den oändliga) anropskedjan är klar.

Medlem sedan apr. 2006244 inlägg
#9

Nej "anropskön" ska aldrig stängas. Den ska köra på i all oändlighet. Visste inte att variablerna stannade kvar i minnet. Jag trodde att de skrevs över:) Hur ska jag nu modifiera scriptet för att få detta att funka då?

Medlem sedan mars 20034 471 inlägg
#10

Det kan aldrig fungera. I princip har du skapat en oändlig loop.

Här gäller det att tänka om!

Medlem sedan apr. 2006244 inlägg
#11

Men kan man inte tömma minnet/variablen på något sätt?

Medlem sedan mars 20034 471 inlägg
#12

vic skrev:

Men kan man inte tömma minnet/variablen på något sätt?

Nej. Och om du kunde skulle du bara såga av grenen du satt på.

Du får tänka om från början. Vad vill du åstadkomma?

Medlem sedan apr. 2006244 inlägg
#13

F1 - Kollar hur många divvar det finns.

F2 - Visar divvarna, en åt gången. Detta rullar på i tills alla divvar har visats sedan aktiveras F1 för att återigen kolla hur många divvar det finns.

F3 - Samtidigt som F2 och F2 rullar runt så hämtar jag in nya divvar med ajax, alternativt kan det försvinna lite divvar också. Det är av den anledningen som man måste kontrollera hur många divvar det verkligen finns med F1 istället för att bara rulla runt på de divvar som finns när sidan laddas.

Till saken hör att detta fungerar utmärkt i 5 minuter, divvar visas/byts ut etc... sen skiter det sig

Nu har jag bara kört en iframe där jag endast kör F1 en gågn och låter sedan F2 rulla runt bland divvarna utan att anropa F1 på nytt. Sedan efter 5 minuter låter jag sidan i Iframeén ladda om sig själv. Detta funkar men känns inte som en särskillt rolig lösning :(

Medlem sedan mars 20034 471 inlägg
#14

Lagra id för alla befintliga divar i en array, myDivs. Efterhand som divar läggs till stoppas de in, och tas de bort från sidan, tar du bort dem ur arrayen. På så sätt innehåller myDivs alltid de divar som ligger på sidan nu. ==> F1 behövs inte.

331 ms totalt · 4 externa anrop · v20260731065814-full.86ec41c2
171 ms — deklarationer (db)
0 ms — hämta statistik (cache)
152 ms — hämta tråd, inlägg och bilagor (db)
175 ms — ändringar (db)