Question

I'm using Moment.js to handle time. 10 Inning objects (durations) have properly been defined with start and end times, as shown in this question's JSFiddle.

This script is meant to use the the difference between an Inning end time and the present to define the necessary Timeout to be set for a function endInning() to be called. This is implemented within a loop to handle the 10 Innings.

for (x = 0; x < 10; x++) { // for each of ten defined innings

    // calculate the difference between the end of inning x and now
    timeTillEnd = moment(Game.innings[x].start).diff(moment(now),"milliseconds");

    // and set the necessary delay
    setTimeout(function () { 
        endInning(x);
    }, timeTillEnd);

}

However, instead of resulting in delays that increment by 12 hours, each delay is the same.


The result:

  • Ending Inning 1 on Friday, 12:00 PM, 412712000 ms from now.

  • Ending Inning 2 on Friday, 12:00 PM, 412712000 ms from now.

  • Ending Inning 3 on Friday, 12:00 PM, 412712000 ms from now.

  • ...and so on, until Inning 10.


What's my mistake and how can I fix it?


Edits:

After asking questions related to my practices with this script, I think that these questions / answers are related:

So my question becomes: How can I apply this practice to my specific situation?

Was it helpful?

Solution

Actual problem with ending dates does not belong to timeouts (however, that's still a problem with them)

first - you created one inning object while you need to create 10

so, move

var inning = new Object();

inside the first for loop, this way you will create 10 inning objects instead of one.

second - you misused moment library object

inning.start = beginning.moment.add("hours", (inningHours * x)); //WRONG

you just modified beginning.moment variable which is not what you trying to achieve!

In javascript, all objects are passed by references https://stackoverflow.com/a/16880456/870183

So, you must create new moment object and then modify it.

inning.start = moment(beginning.moment).add("hours", (inningHours * x)); //correct

third - timeout problem. For every timeout we need to create another function with another x variable

Closures was hard to understand for me, so keep trying. https://stackoverflow.com/a/111200/870183

Let's create a function which will return another function

function endInningFunc(x){
    return function () {
        endInning(x)
    }
}

and then we will pass new function where x will be "locked" to its value to setTimeout

setTimeout(endInningFunc(x), timeTillEnd);

last thing, don't use global variables! http://www.webdevelopersnotes.com/tutorials/javascript/global_local_variables_scope_javascript.php3

for example, for (var x=0);

finally, the working example. http://jsfiddle.net/LmuX6/13/

OTHER TIPS

function doSetTimeout(i) {
  setTimeout(function() { alert(i); }, 100);
}

for (var i = 1; i <= 2; ++i) {
  doSetTimeout(i);
}

copied it from setTimeout in for-loop does not print consecutive values I won't use it if I am looping too much as every function call is creating a new function object and it will be memory intensive if you are looping too much, alternative would be to create a class like structure. example http://www.phpied.com/3-ways-to-define-a-javascript-class/

function Inning(x) {
    this.x= x;
}

Inning.prototype.onTimeOut = function() {
    // do your thing with this.x
};
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top