AleRemote225
AleRemote225

Reputation: 113

Dynamic setTimeout causes "maximum call stack exceeded" error

I am trying to create setTimeout that will call function and then function will call setTimeout again but with different interval value.

The issue is that it seems to fall into infinite loop.

These are starting variables:

var interval = 1500;
var elapsed = 0;
var totalTimer = 40000;
var startTime = null;

This is the function:

function playLights(){
        startTime = Date.now();
        interval = (totalTimer-elapsed) * 0.026;
        lights[0].color(0, 91, 68, 3500, 0);
        lights[1].color(0, 91, 68, 3500, 0);
        setTimeout(function(){
            lights[0].color(0, 100, 100, 3500, 0);
            lights[1].color(0, 100, 100, 3500, 0);
        }, 300);
        elapsed = Date.now() - startTime;
        if((Date.now() - startTime) < 37000){
            setTimeout(playLights(), interval.toFixed());
        }
        console.log("Interval: "+interval+" ,Elapsed: "+elapsed);
    }

When action happens I call playLights();

What's supposed to happen:

1) Bomb gets planted in game,

2) It must call playLights(),

3) It must get current time and save it,

4) It must determine interval, so since it's first call - it must be 1040 ms.

5) It must flicker colors. (Not important right now)

6) Then it must calculate how much time elapsed based on currentDate - storedDate.

7) Then it must check if elapsed time is more than 37000 ms (37 seconds)

If yes - setTimeout on itself.

If not - just nothing.

I keep getting maximum call stack exceeded by Node.js

Did I make mistake somewhere which causes it to fall into infinite loop?

Upvotes: 2

Views: 200

Answers (1)

d3vi4nt
d3vi4nt

Reputation: 130

There are several mistakes in your code, for example
In your function you set startTime to Date.now() it's alright, BUT! at the very next moment you set elapsed to Date.now() - startTime so it will be always 0, because startTime equals Date.now(). Then you just do the same thing in the statement of your if section, it will be always true. SO basicly nothing changes, and that leads to an infinite loop etc.. Either you can set startTime in your main function, or pass it thru playLights() function. Finally you have to pass startTime to the callback function in setTimeout() you can do it like so:

`setTimeout(function() {playLights(startTime);}, interval.toFixed());`

so your code would look something like this:

function playLights(startTime) {
    interval = (totalTimer-elapsed) * 0.026;
    lights[0].color(0, 91, 68, 3500, 0);
    lights[1].color(0, 91, 68, 3500, 0);
    setTimeout(function() {
        lights[0].color(0, 100, 100, 3500, 0);
        lights[1].color(0, 100, 100, 3500, 0);
    }, 300);
    elapsed = Date.now() - startTime;
    if (elapsed < 37000) {
        setTimeout(function(){playLights(startTime)}, interval.toFixed());
    }
    console.log("Interval: "+interval+" ,Elapsed: "+elapsed);
}

And you can call it like this:

playLights(Date.now());

Upvotes: 2

Related Questions