I'm calling this a browser crash, but more like an infinite loop - I'm hardly a javascript expert. What happens is a game gets to it's end, and the browser (in this case firefox) just goes on and on and on - more like a freeze, no snap, error message, no nothing. You have to close down the browser completely. Now the really odd thing about this is this works perfectly fine - off line. This just happens online. And the other odd thing about this is that (in the code) the first time it resets the game - this also works perfect both online and off. Just the second time.
Like this: (this is part of it)
function resetGame(){
//reset game
Ok the above works online and off, player gets dumped out of game, starts over. Then however;
function moveToEndGame(){
console.log("TIMER END");
var twn = game.add.tween(bg).to({alpha:0},tween_speed,"Linear",true);
twn.onComplete.addOnce(function(){flagGameover = true;},this);
}
if(!flagGameover && !star.visible && idx_bullet < bullet_array.length)
initBullet();
else{
if(flagGameover){
console.log("GOTO GAMEOVER");
window.location = "../endgame.html";
}
}
}
}
OK, offline it goes directly to endgame.html online, it freezes up, crashes, infinitive loop, whatever you want to call it.
Anyone have any idea why?
OK, spent hours and hours on this (the programmer who did this part has since disappeared). Even went back 2 weeks ago to the code as it was, yup, that does the same thing - infinite loop.
So now I'd like to find a way to just 'abort the javascript' right at the end of the 21 second timer. I've run across a number of things from other posts such as:
// creates a new exception type:
function FatalError(){ Error.apply(this, arguments); this.name = "FatalError"; }
FatalError.prototype = Object.create(Error.prototype);
or
function javascript_abort()
But....
Even if you throw an exception, it will only kill the current event loop. Callbacks passed to setTimeout or DOM/XMLHttpRequest event handlers will still run when their time comes.
or something with this:
functions (setTimer and two setIntervals)
OR
function clearTimer() {
clearInterval(intervalTimer);
}
Anyway, here are the sections in the code pertaining to the 21 second timer:
var maxTime = 21; //in SECOND
var timerEvent = null;
This is where the timer gets added (after a 3 second animation)
console.log("FINISH ANIMATION and ADD TIMER");
and this
timerEvent = game.time.events.add(Phaser.Timer.SECOND * maxTime, moveToEndGame, this);
},this);
function moveToEndGame(){
console.log("TIMER END");
var twn = game.add.tween(bg).to({alpha:0},tween_speed,"Linear",true);
twn.onComplete.addOnce(function(){flagGameover = true;},this);
}
-----------> and THE END (or supposed to be the end)
if(!flagGameover && !star.visible && idx_bullet < bullet_array.length)
initBullet();
else{
if(flagGameover){
console.log("GOTO GAMEOVER");
window.location = "../endgame.html";
}
}
}
}
So is it possible to kill the timer at the end of 21 seconds and everything else with it and just have the player go to endgame.html ????????? i didn't mention the phaser console.log - can it be done that way? Anyone do something like this before, basically a javascript salvage operation.
I found out what it was.
It was missing a callover, as in:
var callGameover = false;
and......
if(flagGameover){
if(callGameover == false){
callGameover = true;
console.log("GOTO GAMEOVER");
window.location = "endgame.html";
I didn't know that was enough to cause an "infinite loop" but apparently it was. Put the above in and loop gone!
I have this while loop in JS. It tries to do something and if it doesn't work, I want it to calculate the time it will need to wait and then reloop.
while (makeSomething() == false) {
var wait = a + b + c;
sleep(wait);
}
I only know setTimeout(), but as you might know it does not behave like I want it to do.
If jQuery offers a solution for it, that would be okay too.
You are going to have to change how your logic works. Probably means you need to break up your code. Basic idea of what you want to do it:
function waitForIt(){
if(makeSomething() == false) {
var wait = a + b + c;
window.setTimeout(waitForIt, wait);
} else {
console.log("do next step");
}
}
waitForIt();
It depends on your intention here. From your question, it seems you want to stay in the while loop until makeSomething() is true. epascarello's answer will continue thread execution because it uses setTimeout().
Technically his answer is significantly better because it does not hang the application. But if you really wanted a sleep function that will stop all application processing you can use this function:
function sleepFor( sleepDuration ) {
var now = new Date().getTime();
while(new Date().getTime() < now + sleepDuration){ /* do nothing */ }
}
Note that this is generally bad practice, a user will not be able to interact with your application while the thread is asleep.
Gathered from: What is the JavaScript version of sleep()?
What this is all about
I am currently working on a script for emoticons on the Campfire Chat Service since they don't have an emoticon feature. Right now it is running the emoticon really slowly since it uses a setInterval that is suppose to check ever 200 milliseconds if there is a new message in the chat. I do this by making two variables "a" and "b" with var a,b;. So then in the first setInterval I time it with 150 millisecond. Inside of this I just give the variable "a" the value of the HTML of the chat. Then in the second setInterval (200) I give the variable "b" the value of the HTML too but this is a different timing so now I check the HTML in an if statement and if it is different I run the function to change the Symbol to an emoticon. I did it this was to improve performance. Before it would check for emoticons even though no one in the Campfire Chat actually wrote something so there is no need to check for emoticons.
This is the complete function:
var a, b;
setInterval(function() {
a = $('#chat').html();
console.warn("Chat HTML has been Scanned");
}, 150);
var t = "0";
setInterval(function() {
b = $('#chat').html();
console.warn("Chat got scanned for Change in html.");
if (emoOn == true) {
if (t === $('#num12345').text()) {
$(".participants").after('<div id="emote"><h3><span class="room_actions">On | Off</span>Emoticons</h3></div>');
$('#num12345').text("111")
}
if (a !== b) {
turnOn();
console.log("CHANGE")
} else {
turnOn("off");
}
}
}, 200);
The problem
As you can see in the above code I run 3 consoles. In the consoles I expect the "Chat HTML has been Scanned" warning to come for and then the "Chat got scanned for Change in html." in that order for the whole time. But instead the "Chat HTML has been Scanned" warning shoes up twice it just doesn't work like I image it to work.
And when a new message shows its suppose to log "Change" but most of the time it doesn't and I think it is the problem of the setIntervals. It seems like they aren't timing right. But I really don't wanna say that JavaScript is causing this issue but I don't know what else it could be. Also I'm using Chrome.
setInterval is asynchronous, so when your first call is waiting, the javascript interpreter moves on to it's next job (in this case setting t to "0" and then your second setInterval call).
Edit: I think the problem is that you're defining your setInterval calls at the same time, yet the precision of javascript timers is not that great (see here: http://ejohn.org/blog/accuracy-of-javascript-time/).
You could call the second setInterval after a setTimeout to give yourself a bit of a buffer:
var a, b;
setInterval(function() {
a = $('#chat').html();
console.warn("Chat HTML has been Scanned");
var t = "0";
}, 2000);
setTimeout(function(){
setInterval(function() {
b = $('#chat').html();
console.warn("Chat got scanned for Change in html.");
if (emoOn == true) {
if (t === $('#num12345').text()) {
$(".participants").after('<div id="emote"><h3><span class="room_actions">On | Off</span>Emoticons</h3></div>');
$('#num12345').text("111")
}
if (a !== b) {
turnOn();
console.log("CHANGE")
} else {
turnOn("off");
}
}
}, 2000);
}, 500);
This will set up the second call to setInterval half a second after the first, you could get away with a lot less than that though (anything over 30ms should be enough).
I am trying to make a function that starts in exact intervals to keep stanble update rate. The problem is that it seems to execute in 2 channels. This is the log:
timeElapsed=141; lastDraw=1314040922291
timeElapsed=860; lastDraw=1314040923151
timeElapsed=141; lastDraw=1314040923292
timeElapsed=860; lastDraw=1314040924152
timeElapsed=141; lastDraw=1314040924293
timeElapsed=860; lastDraw=1314040925153
timeElapsed=141; lastDraw=1314040925294
timeElapsed=860; lastDraw=1314040926154
timeElapsed=141; lastDraw=1314040926295
timeElapsed=859; lastDraw=1314040927154
timeElapsed=143; lastDraw=1314040927297
timeElapsed=858; lastDraw=1314040928155
timeElapsed=143; lastDraw=1314040928298
timeElapsed=858; lastDraw=1314040929156
timeElapsed=142; lastDraw=1314040929298
First, I exectute my function using
drawTimer = setTimeout(function(){ draw() }, 1);
and the function looks like this:
var draw = function(){
if(!running)
return;
var miliseconds = getCurrentMiliseconds();
var timeElapsed = miliseconds - lastDraw;
lastDraw = miliseconds;
console.log("timeElapsed=" + timeElapsed + "; lastDraw=" + lastDraw);
onDrawListener(timeElapsed);
if(timeElapsed < timeLapse)
miliseconds = timeLapse - timeElapsed;
else
miliseconds = 1;
drawTimer = setTimeout(function(){ draw() }, miliseconds);
}
It happens in both, Chrome and Firefox. Do you know what is it caused by? And... How to fix it?
P.S. Since everyone seems to be so confused about the running variable, here it is: it's a private parent object member that indicates whether the mechanism is still running or has stopped. It's set by other functions and is just there to make sure this function doesn't continue working after stop() is called.
-- update --
timeLapse is set to 1000 (1 time per seconds) and never changed again.
onDrawListener is set to this function:
function(timeElapsed){
canvas.clear();
moveSnake();
if(snake.body[0] == food){
food = getRandomFreePosition();
++snake.body.lenght;
}
drawBackground();
drawFood();
drawSnake();
}
to explain it: canvas is kinda the engine that takes care of callbacks, key listening and also has a few functions. Other than that seems kinda self-explaining. they do nothing other than some int algorithms and drawing in the canvas.
-- Figured out --
I understood that I should calculate time spent for current function and not since the last one started. My old method worked not in 2 channels but rather in long-short-long-short-long-... delayes
first of all you dont set the running bool and also when you enter the function immediately do a on clearTimeout on drawTimer.
clearTimeout(drawTimer);
In a loop like that, you should consider to write:
if(timeElapsed >= AMOUNT_OF_TIME)
{
// run code
}
So I made some timers for a quiz. The thing is, I just realized when I put
javascript: alert("blah");
in the address, the popup alert box pauses my timer. Which is very unwanted in a quiz.
I don't think there is any way to stop this behaviour... but I'll ask anyway.
If there is not, mind suggesting what should I do?
Never, ever rely on javascript (or any other client-side time) to calculate elapsed times for operations done between postbacks, or different pages.
If you always compare server dates, it will be hard for people to cheat:
first page request, store the server time
ping with javascript calls each N seconds, compare the 2 server times, and return the elapsed (just for show)
when the user submits the form, compare the 2 server times, calculate the elapsed time, and discard the ones which took too long (ie: possible cheaters)
Apparently the preview rendering differs from the posted rendering. This paragraph is here to make sure the next two lines show up as code.
// Preserve native alert() if you need it for something special
window.nativeAlert = window.alert;
window.alert = function(msg) {
// Do something with msg here. I always write mine to console.log,
// but then I have rarely found a use for a real modal dialog,
// and most can be handled by the browser (like window.onbeforeunload).
};
No, there is no way to prevent alert from stopping the single thread in JavaScript. Probably you can use some other way of user notification, for example a floating layer.
It's modal and stops execution. Consider an alternative which does not pause execution like a Lightbox technique.
I think the question asker is trying to prevent cheating. Since a user can type javascript: alert("paused"); into the address bar, or make a bookmarklet to do that, it's easy to pause the quiz and cheat.
The only thing I can think of is to use Date() to get the current time, and check it again when the timer fires. Then if the time difference is not reasonably close to the intended timer duration, show an admonishment and disqualify the answer to that question or let them flunk the quiz. There is no way to prevent the user from pausing your quiz, but it should be possible to catch them.
Of course with any cheat-proofing, you motivate people to become better cheaters. A person could change the system time on their PC, and fool the javascript Date() constructor which gets the time from the operating system.
You can use an interval to do a repeated clock comparison against a one second interval length. The interval handler can also update a time-remaining field on the user's display. Then the users can feel the pressure build as time runs out on their quiz. Fun times!
The feedback loop on SyaZ's question has clarified the issues at stake.
Here's an attempt to summarize the good answers so far:
Client scripts are by nature are easy to manipulate to cheat an online quiz. SEE #Filini 's Server-side approach
window.alert = function(msg) {} will overriding alert() and perhaps defeat the low hanging fruit of putting in the addressbar: javascript:alert('Pausing page so I can google the answer') or I'll use my Phone-A-Friend now. Courtesy of #eyelidlessness
If you must use a client-side approach, instead of using setTimeOut(), you could use a custom date-compare-based pause function like this (concept by #Mnebuerquo, code example by me (#micahwittman)):
Example:
var beginDate = new Date();
function myTimeout(milsecs){
do { curDate = new Date(); }
while((curDate-beginDate) < milsecs);
}
function putDownYourPencils(milsecs){
myTimeout(milsecs);
var seconds = milsecs / 1000;
alert('Your ' + seconds + ' seconds are up. Quiz is over.');
}
putDownYourPencils(3000);
Ultimately, you cannot trust user input. Without keeping track of the time elapsed on the server, there's just no guarantee the data hasn't been manipulated.
However, if you're confident your quiz-takers aren't JavaScript-savvy, and are merely relying on a "trick" they found somewhere, you could test for cheating (pausing) with the following code, which doesn't require modifying window.alert:
var timer = {
startDatetime: null,
startSec: 0,
variance: 1,
exitOnPause: true,
count: function (config) {
var that = this;
if (typeof config == "object" && typeof parseInt(config.seconds) == "number" && !isNaN(parseInt(config.seconds)))
{
if (typeof parseFloat(config.variance) == "number" && !isNaN(parseFloat(config.variance))) this.variance = config.variance;
if (typeof config.exitOnPause == "boolean") this.exitOnPause = config.exitOnPause;
if (config.seconds > 0)
{
if (!this.startSec) this.startSec = config.seconds;
if (!this.startDatetime) this.startDatetime = new Date();
var currentDatetime = new Date();
if (currentDatetime.getTime() - this.startDatetime.getTime() > (this.startSec - config.seconds) * this.variance * 1000)
{
if (typeof config.onPause == "function") config.onPause();
if (!this.exitOnPause)
{
this.startDatetime = new Date();
this.startSec = config.seconds--;
window.setTimeout(function () { that.count(config); }, 1000);
}
}
else
{
config.seconds--;
window.setTimeout(function () { that.count(config); }, 1000);
}
}
else
{
if (typeof config.onFinish == "function") config.onFinish();
}
}
}
};
This timer object has a single method, count(), which accepts an object as input. It expects a seconds property in the input object at minimum.
For some reason, window.setTimeout doesn't always work as expected. Sometimes, on my machine, window.setTimeout(x, 1000), which should execute the code after 1 second, took more than 2 seconds. So, in a case like this, you should allow a variance, so people who aren't cheating don't get flagged as cheaters. The variance defaults to 1, but it can be overridden in the input object. Here's an example of how to use this code, which allows 2.5 seconds of "wiggle room" for slow-pokes:
timer.count({
seconds: 10,
onPause: function () { alert("You cheated!"); window.location.replace("cheatersAreBad.html"); },
onFinish: function () { alert("Time's up!"); },
variance: 2.5
});
With a solution like this, you could use Ajax to tell a server-side script that the user has paused the timer or redirect the user to a page explaining they were caught cheating, for example. If, for some reason, you wanted to allow the user to continue taking the quiz after they've been caught cheating, you could set exitOnPause to false:
timer.count({
seconds: 10,
exitOnPause: false,
onPause: function () { recordCheaterViaAjax(); },
onFinish: function () { alert("Time's up!"); },
variance: 2.5
});
The server session could be set to expire at say 1 hour. The javascript could be used as only a display tool for the user to know how much time is left. If he decides to cheat by pausing the timer, then he might be suprised when posting his test that his session has timed out.