2

If I call setTimeOut() for say, 10 seconds from now, then execute a set of long running commands, does Node.js/JavaScript wait until those commands finish executing the function set up in setTimeOut? Is the same true with setInterval()?

Are there any things to watch out for if I'm suing both setTimeOut() and setInterval() in the code where tasks may end up being executed around the same time?

I'm using the node-cron (https://github.com/kelektiv/node-cron/blob/master/lib/cron.js) library and I see that it uses setTimeOut. I'm trying to add some tasks using setInterval().

user994165
  • 9,146
  • 30
  • 98
  • 165
  • Just want to reinforce the fact that javascript code executes in a single thread. Your concerns are really vague, so I cant really say anything else. – tcooc Nov 16 '16 at 21:47
  • @tcooc being single threaded does not mean that answer for "does Node.js/JavaScript wait until those commands finish executing" is "yes" – zerkms Nov 16 '16 at 21:50
  • @Alejandro, thanks but I didn't see any reference to setInterval() in that question. – user994165 Nov 16 '16 at 21:53
  • @user994165 Both function in basically the same way. Imagine `setInterval` as a `setTimeout` that calls `setTimeout` when it's called. I'm voting to close this question because it's unclear what you're asking. – tcooc Nov 16 '16 at 22:00

2 Answers2

4

Timer events in node.js are not guaranteed to be called at an accurate time.

If I call setTimeOut() for say, 10 seconds from now, then execute a set of long running commands, does Node.js/JavaScript wait until those commands finish executing the function set up in setTimeOut?

Yes, it waits until the current code executing in node.js is done before it can serve the next timer event.

Is the same true with setInterval()?

Yes, same mechanism for setInterval().

Here's some explanation of how the node.js system works.

node.js is a single threaded event-driven system (technically threads are used inside of node.js, but it only runs one single thread of your JS code).

When you use setTimeout() or setInterval() some internal mechanism inside of node.js uses system timers to know when the next timer should fire. At that moment, an event is inserted into the node.js event queue. If node.js is doing nothing at that moment, then the event is triggered immediately and the appropriate callback function is called immediately.

But, if node.js is busy running code and if other events are in front of the timer event in the event queue, then the timer event will not be triggered immediately.

Instead, node.js will wait until the current thread of execution in node.js is done and then, and only then, the next event in the event queue will be pulled out and the appropriate callback for that event will get called.

So, if you have some piece of long running node.js code, it will block all other events (including timer events) until it is done and node.js can get back to pulling the next event out of the event queue.

jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • 1
    @zerkms - Did you not see the words in my answer that come immediately after "node.js is a single threaded event-driven system" where it says "(technically threads are used inside of node.js, but it only runs one single thread of your JS code)"? – jfriend00 Nov 16 '16 at 22:16
  • I do not indeed. I have no good explanation how I did not see it o_O – zerkms Nov 16 '16 at 22:17
  • 1
    @zerkms - It was added as an edit, but added before your comment shortly after posting. So, maybe you were viewing a version before the edit. – jfriend00 Nov 16 '16 at 22:18
0

The answer is: maybe but probably not.

When things are async, there isn't necessarily any guarantee what's going to get called when. When async things are called, it'll get added to an internal queue and it'll process the queue. Odds are, they will finish, but it is not something you should rely on.

Instead, what you should do is trigger something to explicitly indicate that it finished. There are lots of ways to go about it, such as callbacks and Promises. You could even set a boolean that indicates the state and check it before the dependent step.

let aDone = false;

setTimeout(() => { aDone = true; }, 1000);

const startInterval = () => {
    if (!aDone) {
        setTimeout(startInterval, 200); // try again in 200ms
    }

    setInterval(() => { /* do something */ }, 1000);
};

startInterval(); // kick off the interval check
samanime
  • 25,408
  • 15
  • 90
  • 139
  • "but it is not something you should rely on" --- what does this exactly mean? Will it finish or not? – zerkms Nov 16 '16 at 21:50
  • @zerkms It means you can't be sure if it will finish or not, so use another mechanism if you need that certainty. – Alejandro C. Nov 16 '16 at 21:55
  • @zerkms Basically, you can't trust it. 9 out of 10 tests may work, but 1 doesn't. It's a race condition. (Edit to remove recommendation to check out Wiki, didn't notice zerkms != OP) – samanime Nov 16 '16 at 21:58
  • 2
    @AlejandroC. "It means you can't be sure if it will finish or not" --- with nodejs you can be sure it will. Unless you explicitly ask event loop to terminate. – zerkms Nov 16 '16 at 22:03
  • @samanime my complaint was more about wording: it's not clear whether you're addressing the order (which may be not deterministic) or the fact that it will eventually finish (which it certainly will) – zerkms Nov 16 '16 at 22:04
  • @zerkms, wait, you're saying there's some guarantee that all functions somehow terminate? – Alejandro C. Nov 16 '16 at 22:05
  • @AlejandroC. if something was scheduled by an event loop to be invoked - it will be invoked. `setTimeout(() => {}, 10000);` --- this code is guaranteed to hold node process for at least 10 seconds. (unless you explicitly let an event loop to teminate prior to that) – zerkms Nov 16 '16 at 22:06
  • @zerkms so if I setTimeout with an infinitely looping function, and then setTimeout for later with another function F, my infinite loop will be preempted and F will be called? I thought preemption didn't happen in node. – Alejandro C. Nov 16 '16 at 22:08
  • @AlejandroC. it's not about preemption. It will not be preempted for sure. – zerkms Nov 16 '16 at 22:08
  • 1
    @zerkms I see, you're saying the event loop won't terminate early; however there's no guarantee that progress will be made through the queue. That's what I get for losing the context of the question. :-) – Alejandro C. Nov 16 '16 at 22:09
  • @AlejandroC. yep, that's what I meant. The thunks to be invoked are strictly ordered but the order may be not what users expects. – zerkms Nov 16 '16 at 22:10
  • @AlejandroC. "That's what I get for losing the context of the question. :-)" --- there are at least 3 different questions asked there, no wondering we are mis-understand each other :-) – zerkms Nov 16 '16 at 22:10