Work around getElementById - javascript

I'm making an website game which uses many document.getElementById inside a setInterval that runs every 0.25 sec. This makes my webbsite slow after some time. I'm quite new to Javascript but I wonder if there's a more effective or efficient way to call and update a HTML element or create a effective loop that includes game latency and runs every 1 sec?

Precache all ID's.
Something in the lines of (pseudo code):
var all_objects = [];
...
onCreateObject = function(){
all_objects.push(newObject.id)
}
and then just iterate through the all_objects variable.
As for the loop itself, there are solutions out there already: http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/

set variables outside (above) your setInterval function:
var myDiv = document.getElementById("ID");
and then call them inside the setInterval function:
myDiv.something()

Related

Create a unique function name on the fly for shared timer

I'll start with the exact nature of the problem and then give some background. I am trying to name a function -threadTimer- and give it a random unique identifier, such as 'threadTimer'+ID. A randomly generated ID would work fine. Then, I need to use setInterval on it, to make it fire repeatedly and therein lies my coding problem. I have tried every variation of new, function, function as an object and I just can't get my head around it. You'll notice that the function I have created is an object and perhaps this is where I'm going in circles.
OK, the background I mentioned. threadTimer is fired by a master timer co-ordinating several threads. That's why you'll see I have generated a 'global' object for reference elsewhere. similar HTML entities can fire threadTimer at the same time, hence my requirement to make each instance unique.
window['GlblThreadExe'+ID]=setInterval(function(){threadTimer(elid,parent,lft,top,diameter,point,bStyle,color,grp,startTime,size,ID,counter,div,divwth,divht,wthIncrement,htIncrement,lftStart,topStart,lftIncrement,topIncrement)},interval);
function threadTimer(elid,parent,lft,top,diameter,point,bStyle,color,grp,startTime,size,ID,counter,div,divwth,divht,wthIncrement,htIncrement,lftStart,topStart,lftIncrement,topIncrement){
// more code
}
In truth, I think its the volume of parameters that I'm passing that's confusing my syntax. Any help appreciated
Avoid polluting window
Generally instead of polluting the global namespace you can store your setInterval ids in some variable
let intervalIds = {}
intervalIds['GlblThreadExe'+ID] = setInterval(function()...)
If really necessary, then store intervalIds to window
window.intervalIds = intervalIds;
Wrap your anonymous function
When you create the "clock", do not call setInterval directly:
Here, createTimerWithId will return a function which calls threadTimer
Dirty id generation
Use a timestamp, and mix it with some random stuff. Or better use a UUID
setInterval(createTimerWithId(), 1000)
function createTimerWithId(){
let id = Date.now()+Math.random(); //no lib, oneliner. good enough to debug
return function(){//the same function you gave to setInterval in your example
threadTimer(id, ...)
}
}
We can do better
In 1. we generated an id on the fly and thus
your code is not testable (id will always change(well except if you mock Math and Date...)).
your id is ugly (a float...)
it will be hard to know from which setInterval you come from
instead, give it the ID.
function createTimerWithId(ID){
return function(){//the same function you gave to setInterval in your example
threadTimer(ID, ...)
}
}
window['..'+ID] = setInterval(createTimerWithId(ID));
shorter version being
window['..'+ID] = setInterval((id=>{
return function(){
threadTimer(id, ...)
}
})(ID),1000);

Javascript setTimer

I'm having a hard time understanding the logic behind the setTimer method in javascript.
<html><head>
<script>
function Timer () {
var today = new Date();
var h = today.getHours();
var m = today.getMinutes();
var s = today.getSeconds();
document.getElementById('show').innerHTML=h+":"+m+":"+s;
t = setTimeout("Timer()", 1000);
}
</script>
</head>
<body onload="Timer()">
<div id="show"></div>
</body></html>
setTimeout is used to delay a function/method execution. Then why it is being used in a real-time clock?
t = setTimeout("Timer()", 1000);
This part is confusing.
The clock is recursively calling itself, after the elapsed period of time.
Making a real-time clock is impossible in JS.
Because of how JS engines work, if you put Timer in a loop, to run for an infinite period of time, you'd never see the time update on the screen (as changes aren't drawn to the window until a function finishes and there's a gap in the program).
Also, inside that infinite-loop, it would be impossible to do anything else with the page (even closing it), because JS can only do one thing at a time, so it can't listen to any of the user's clicking until it's done with this loop.......
So that's what the setTimeout is for.
Timer is the function which acts as the clock.
Inside of the Timer function, at the end when all of the work is done, it's telling setTimeout to wait 1 second (1000ms) and then to call a function called Timer.
Timer just so happens to be the same function. But setTimeout doesn't know that, and doesn't care.
The t in this case is largely useless. setTimeout will return a number -- like taking a number at the doctor's office.
If, before you go through with it, you decide to back out, you can call clearTimeout(t); and it'll skip over that call (in this case, it would stop calling the clock).
There are a few bad-practices in here, that I figure I should mention, so that you can try not to copy them in your own practice.
First:
Pass setTimeout a reference to a function, and not a string...
var runThisFunction = function () { console.log("It's the future!"); },
time_to_wait = 250;
// DON'T DO THIS
setTimeout( "runThisFunction()", 250 );
// DO THIS
setTimeout( runThisFunction, 250 );
The difference is that setTimeout will run that string through eval, which can be a huge security concern depending on what you're trying to do.
The second problem is setting a random global variable, t... ...and hoping to use that as a solution.
First, in a couple of years, JS engines are going to start yelling at people for doing that stuff. Second, it's a huge hole, because any part of any app on that page could then overwrite t, or you could be relying on t somewhere else in your script, but every 1000ms, it gets written over with a new number.
Instead, they probably should have used a Timer.start(); and Timer.stop(); setup.
Your code:
t = setTimeout("Timer()", 1000);
The first thing you should know is that it's considered bad practice to put the first parameter in a string -- it should be the function name, unquoted, and without brackets, like so:
t = setTimeout(Timer, 1000);
That aside, your question about why it's being used to display a clock:
The use of setTimeout() inside the Timer() function to call itself is a common Javascript pattern to get a function to be called repeatedly. setTimeout() itself only triggers the function to be called a single time, after the given period of time has elapsed, so for a repeating event it needs to be re-triggered every time.
Since the setTimeout call is inside the Timer() function, it won't be set until Timer() is called the first time by some other means. This is where the body onload comes in.
As you suspect, setTimeout() isn't an accurate method for guaranteeing that a function will be called after exactly a given amount of time. Javascript is not multi-threaded, so any event handlers that are triggered must wait for any other code that is running at the same time. If something else is running slowly, this may cause your timer not to be triggered at exactly the moment it wants to be.
However, this isn't really a problem for your clock , because the clock is setting itself to the actual system time rather than relying on the setTimeout loop to keep itself in sync; the setTimeout loop is simply being used to make sure the display is updated (approximately) once a second. If it isn't actually quite exactly once a second, it doesn't really matter.
I hope that helps explain things a bit better.
When the Timer() function is called, it schedules itself to be run again one second later. The end result is once every second, Timer() updates the show element with the current time. (I have no idea why it's assigned to t, unless t is used in some other code on the page.)
The line starts The function again after one second.

delaying a method of an object with jquery

I'm a jquery novice trying to write my first app here and one thing I've been trying to figure out is how to use the .delay() method if what I want to delay is the method of an object.
So for example, I have something like this:
dice = new Dice("#die1", "#die2");
dice.roll();
But I want there to be a delay before the roll() function is actually invoked. How would I do that?
I figured using jquery would be easier than pure javascript because I know that using setTimout() is tricky to use with your own methods.
There is nothing tricky or dangerous about setTimeout and it's likely the most appropriate approach here. It's specifically designed to execute functions after a given time has expired.
For example here's a 1 second delay
dice = new Dice("#die1", "#die2");
setTimeout(function() { dice.roll(); }, 1000);

Simultaneous code in javascript?

How do I have two separate functions run simultaneously? If I wanted two clocks, one to count up and the other to count down, and I wanted them to run at the same time, how would I do it?
If I just did:
var up = 1;
while(true){
document.write(up);
up++;
if(up==11)
up=1;
}
var down = 10;
while(true){
document.write(down);
down--;
if(down==0)
down=10;
}
...it would just keep counting up...
Javascript is single threaded. There is only one thread that can ever access the page.
It is possible in some HTML5 browsers to use Web Workers to execute some code in another thread and then communicate with the main thread via messaging, but the Web Worker thread cannot access the DOM in any way.
If you want counters to run in a loop, the typical way of doing that is by using timers and then setting the contents of an object in the DOM each time the timer goes. In this way, you can appear to have multiple things running at the same time, but in reality, they are still one at a time, just separately timed.
Here's an example of two counters that "appear" to be running at the same time: http://jsfiddle.net/jfriend00/3yc9r/.
The code for that is this (run after the page is loaded):
var cntr1 = 1;
var cntr2 = 2;
setInterval(function() {
document.getElementById("time1").innerHTML = cntr1 += 13;
}, 33);
setInterval(function() {
document.getElementById("time2").innerHTML = cntr2 += 5;
}, 44);
Also, you really don't want to be doing document.write() in a loop. Code that's going to run for awhile should run after the page is loaded and should modify objects in the DOM directly rather than use document.write().
You would have to put both counters in the same loop, but JavaScript is inherently single threaded, your code example would freeze the browser. Try using the SetTimeout or SetInterval function to fire an event at a specific interval. http://www.w3schools.com/js/js_timing.asp
You don't. Javascript is single threaded. If you wanted a clock you would use asynchrounous timeouts.
// Counts up and down by one per second.
var up = 1;
setTimeout(function() {
up++;
document.write(up);
}, 1000);
var down = 10;
setTimeout(function() {
down--;
document.write(down);
}, 1000);
JS can only ever do one thing at a time (meaning in one single threaded run loop), but it supports lacing asynchronous callbacks together very very well.
You can't, and if you write to the body in a loop, it will be slow.
Instead use setTimeout() to run the next iteration of a forever loop. https://developer.mozilla.org/en/window.setTimeout

is there a sleep() workaround for JavaScript?

So that I could use a loop, and have it pause, say 250 ms after each iteration? [ without setTimeout or setInterval?]
Edit: Ok, so I have a for loop that uses AJAX to post data ($.ajax()) . It has lots of vars in it, like data: 'uid=' + uid, + '&othervars=' + morevars etc, and each loop, the variables change.. so If put that [huge] part into a function() {} [Inside of a setTimeout(), using a counter in the loop to increment the timeout], when it executes, will the actual value be in place where I put the vars?
Current browser implementations are essentially single-threaded, so sleeping in your code will likely block the entire UI. It's not what you want, and just plain isn't how JS works. Refactor your code so that you can use setTimeout.
You will need to use one of javascript's timer functions (setTimeout or setInterval).
There is no real way around them.

Categories

Resources