Reputation: 31
Here is my HTML file, meant to simulate a 3-sphere. When I run it, the page freezes. The Chrome DevTools won't accept any command. Is there an infinite loop that I have missed?
Upvotes: 1
Views: 58
Reputation: 31
The problem was not with the inner while loop, but with the outer one. It didn't have an exit condition.
Upvotes: 0
Reputation: 54026
Every javascript programer is struck from time to time with a locked tab and no easy exit.
If you have the dev tools open you can use the debugger and pause execution, then set a variable to the exit condition.
Example
for(var i = 100; i >= 0; i++){ // force of habit ++ has a infinite loop
// do stuff
}
The loop will not exit but if the devtools is up. Go to the debugger panel and click pause. Then add to the watch list i=-2
. This will set i to the exit condition. Unpause and the loop will exit.
If not in devtools you are stuck and all you can do is close the tab or force it to crash (halt process). To halt the process in Chrome hit [shift][esc] or use menu->More tools->Task manager
to open the task menu. Select the task from the list of running tabs and apps, then click End process
This will stop the execution and clear the tab (The tab will show "Aw, snap!")
Or you can wait for the popup that will appear when the script is blocking for too long and click "kill"
It is very frustrating that javascript does this. It pays that when writing and testing loops with indeterminate exit conditions to add an additional exit clause.
while(true){
if(someThingMayHappen === true){
break;
}
}
This can be a problem during development. The something may never happen and you are then locked out. As a safeguard add a fail safe
var counter = 0;
while(counter < 10000){
counter += 1;
if(someThingMayHappen === true){
break;
}
}
Now if there is a bug your code will still exit and you can track down the bug more easily. You can remove the counter once you are satisfied your code is running correctly.
From a professional standpoint I would never accept a bit of code that does not have an exit condition in the loop statement. "break" and "continue" are in reality goto statements and make your code harder to read.
Another reason to avoid while(true)
is that it confuses the optimisation code. It needs a clear exit condition, and if you obfuscate the exit condition with a break
it will just give up and mark, not just the loop, but the whole function and associated functions as "Not for optimisation" which is not a good thing.Ref Infinite loops with deep logic exit conditions or unclear exit conditions
Even if you want to use a break to exit, trick the javascript engine by adding a fake exit condition.
var loop = true;
while(loop){
if(exitCondition){
loop = false; // not needed but for makes the optimiser happy.
break;
}
}
This will prevent the code from being marked "Not for optimization"
Upvotes: 1
Reputation: 1203
I can't post this on a comment, but have you checked this? You have two while loops, and one is nested... I may be wrong, the code is hard to follow.
Updated (Clarification thanks to Brian):
In the inner loop isClose is compared to some calculation (no assignment done) which if evaluates as true exits the inner loop. After this conditional no assignment is performed on either isClose or on any variables within the first conditional. So if the inner loop isn't exit on the first pass it never will :)
while (true) {
isClose = !isClose;
p0 = project(obj.vertices[ obj.faces[f][v-1] ]);
p1 = project(obj.vertices[ obj.faces[f][ v ] ]);
factor = (5000 - p1[0] - p1[1]) / (p1[0] + p1[1] - p0[0] - p0[1]);
p01 = [p1[0] + factor * (p1[0] - p0[0]), p1[1] + factor * (p1[1] - p0[1])];
polygon = [p01, p1];
while (true) {
v++;
if (isClose != obj.vertices[ obj.faces[f][v % obj.faces[f].length] ][2] > -Math.PI/2)
break;
polygon[polygon.length] = project(obj.vertices[ obj.faces[f][v % obj.faces[f].length] ]);
}
p0 = project(obj.vertices[ obj.faces[f][ v % obj.faces[f].length] ]);
p1 = project(obj.vertices[ obj.faces[f][(v-1) % obj.faces[f].length] ]);
factor = (5000 - p1[0] - p1[1]) / (p1[0] + p1[1] - p0[0] - p0[1]);
p01 = p1 + factor * (p1 - p0);
polygon[polygon.length] = p01;
if (is_clockwise(polygon)) {
p1 = polygon[ 0 ];
pN = polygon[polygon.length - 1];
factor = 5000 / (p1[0] + pN[0] + p1[1] + pN[1]);
p0 = [factor * (p1[0] + pN[0]), factor * (p1[1] + pN[1])];
polygon[polygon.length] = p0;
draw(polygon, obj.colour);
}
}
Upvotes: 1