[SOLVED] Syntax problem creating a countdown timer

Hi,

I’m trying to have a function that is called once every 1 second until a timer reaches 0.
This is what I’m doing but it is not working:

count: function(time) {
 var setTime = time - 1;
 console.log("time left: " + setTime);
        
  if (setTime > 0)
     this.scheduleOnce(this.count(setTime), 1);
}

So if I call the function count(10) I want the console log to count down from 10 each second. Instead what is happening is console log is logging the following instantly as soon as I call the function (no 1 second between calls):

time left: 9
time left: 8
time left: 7
...

And when it reaches 0 it crashes with the error:

Uncaught Error: callback function must be non-null

Anyone know why this is happening or what the correct syntax should be?
Thanks!

1 Like

Firefox refers to Debugger immediately.
Bad place in your code is this.scheduleOnce(this.count(setTime), 1);.
It must be this.scheduleOnce( function() { this.count(setTime)}, 1);

1 Like

And if you allow me some corrections:

count: function(time) {
    cc.log('time left: ' + --time);
    if (time !== 0) this.scheduleOnce( function() { this.count(time); }, 1);
}

Please, avoid var in functions. Using let is more preferable. Let allows you to declare variables.
You can use --variable and variable-- to decrease count (or ++ to increase) without assignment operation.

2 Likes

Thank you so much for the info, will certainly use let now instead of var.
I appreciate all the tips.

Can you help me with one other problem.

When I call the count function a second time before the first time reaches 0, then it begins to output more than one times. For example if I call this.count(10) and then 5 seconds later call it again, it will output more than one ‘time left’ value.

So I call it and get:

time left: 9
time left: 8
time left: 7
...

Then call it again and get:

time left: 9
time left: 6
time left: 8
time left: 5
time left: 7
time left: 4
...

Where 6,5,4 are the continuation of the first call.
I thought calling the function a second time should restart the counter shouldn’t it?

No it shouldn’t.
Each time when you call count() there is new scheduleOnce. Becase count() function is recursive. As result, you have 10 independent schedulers. You should rewrite code. All logic must be in one function.

As example you can set flag. Like let process = true;. And when calling function, it checks if (process) return;. If function is busy now, than do nothing. But you need to remove count() calling from scheduleOnce.
Or try to use schedule( function() { }, 10);. It calls 10 times.

Sorry, I can’t check now. Have an vacation.

1 Like

I see what you are saying now. I can add another parameter that would indicate if this is a new call or a recursive call. So:

scheduleOnce( function() { this.count(time, true); }, 1);
scheduleOnce( function() { this.count(time, false); }, 1);

I don’t want to use schedule( function() { }, 10); because I may not want to run 10 times (I may call it again after 5 times which should then be a total of 15 times not 10 times twice). But now that I think about it, I could add an unschedule() right before each schedule(func() { }, 10); call so it restarts it to 10 every time.

Any suggestions on which method I should use? And thanks for all your input @elitdie