0

In a Node application I have a function that runs every 30 seconds.

It prints to the console using moment().day(). I let it run over night and expected it to notice that the day is now 5 instead of 4 signifying that it is now Friday rather than Thursday. It continued to print 4 when I checked this morning. Why would this be?

Here is a jsfiddle https://jsfiddle.net/9ya2auzy/2/

function checkTheDay(){
    setTimeout(function(){
    document.getElementById("out").innerHTML = moment().day(); 
    checkTheDay();
  }, 2000);
}

checkTheDay();

It will output the current day every 2 seconds. If the page is left open, it should run over night and then print the next number, 6 (at the time of writing) rather than the current ouput 5 (at the time of writing).

Matt Johnson-Pint
  • 230,703
  • 74
  • 448
  • 575
wrldbt
  • 181
  • 2
  • 13
  • @Andreas does my edit make my problem statement more clear? – wrldbt Sep 30 '16 at 13:47
  • 1
    Maybe a timezone problem ? – Weedoze Sep 30 '16 at 13:51
  • @Weedoze - it *could* be related to time zones, if the time zone setting of the computer where this is running is not the same as the OP's local time zone. I suppose if this is code running on a server, where the server is set to UTC or some other time zone, then that might explain it. But we didn't get any information about that from the question. Perhaps the OP could check the output of `moment().format()` to see the result with full time and time zone offset included. That would be useful to diagnose. – Matt Johnson-Pint Sep 30 '16 at 16:10
  • It is an electron app, so the server is actually still on the client's machine. They should both be reading the same timezone info. – wrldbt Sep 30 '16 at 17:21
  • Then it cannot be time zone related. – Matt Johnson-Pint Sep 30 '16 at 18:37

1 Answers1

1

You're recursing into the checkTheDay function once every two seconds. Over a long enough period of time, you're going to exhaust the call stack.

Use setInterval instead of setTimeout and then you will not need to recurse.

function checkTheDay(){
    setInterval(function(){
    document.getElementById("out").innerHTML = moment().day(); 
  }, 2000);
}

checkTheDay();

You can see the effects of the stack growing in your original fiddle by using the Chrome debugger, setting a breakpoint, and looking at the call stack (upper right in the screenshots below).

First Iteration:

First Iteration

Second Iteration:

Second Iteration

Third Iteration:

Third Iteration

As you can see, the call stack is growing. Left unchecked, it will grow out of control until it becomes unresponsive or throws an error.

Matt Johnson-Pint
  • 230,703
  • 74
  • 448
  • 575
  • If there is some potentially long running task inside the `setInterval` then they will start stacking on each other. I am using `setTimeout` to ensure that the task can finish before starting the next iteration. – wrldbt Sep 30 '16 at 15:38
  • 1
    Well, that wasn't part of your question, but you can handle that with a simple `inProgress` flag you set true/false and check to skip any iterations if another iteration is not complete. But you can't just recurse infinitely, or you'll run out of resources one way or another. – Matt Johnson-Pint Sep 30 '16 at 16:04
  • 1
    http://stackoverflow.com/questions/8058612/does-calling-settimeout-clear-the-callstack I should not have to worry about he call stack growing too large. – wrldbt Sep 30 '16 at 17:27
  • Your code is different than the code in that sample, because you are using recursion. See my update for proof. – Matt Johnson-Pint Sep 30 '16 at 18:36
  • I see. You are right. I will have to investigate this farther and see if that is the root cause. I will use `setInterval` over the weekend and see if that gives me back the correct day. – wrldbt Sep 30 '16 at 19:03
  • There's no recursion in the code of the TO... `function a() { a(); }` that would be recursion. Check the callstack in this [fiddle](http://jsfiddle.net/kodw437p/): `function a() { setTimeout(a, 1000); } a();` - @wrldbt Yes, you don't have to worry about the call stack, as you've already seen in the answer of your link – Andreas Oct 01 '16 at 09:53
  • It seems that using setInterval was able to log the correct day. I'm still not sure if the call stack is the culprit though. – wrldbt Oct 03 '16 at 13:08
  • Regardless of possible recursion, I accepted the answer because changing it to `setInterval` fixed my problem. – wrldbt Oct 07 '16 at 15:09