BaldEagle
BaldEagle

Reputation: 1028

Is node.js setTimeout() working?

I'm new to Node.js. Is there something I need to do to get setTimeout() to work?

Here's a code snippet.

async code that sets appMsg.doneLoadTables = true when done

do {
  console.log('waiting ...   ' + appMsg.doneLoadTables);
  setTimeout(function() { console.log('waiting ...'); }, 1000);
} while (!appMsg.doneLoadTables);

Symptoms:

I had this experience with Node 4.2.1; I continue to have this experience after installing Node 5.0.0.

I've seen that similar questions about setTimeout() have been asked here many times before. I hope my use of a IIFE inside setTimeout() makes this question distinct from all of those.

Thanks in advance for any help offered ...

Upvotes: 2

Views: 396

Answers (3)

sergeyz
sergeyz

Reputation: 1337

(While the two calls to console.log are similar, only the first prints the value of appMsg.doneLoadTables.) Every result includes that value.

That is the correct behavior since you never exit the while loop. You stay in the same event frame that keeps looping forever.

The spacing between calls to console.log is much closer than 1000 msec. (I suspect the spacing is as fast as the computer can process the loop shown here.)

That is the correct behavior again because you callbacks that you passed to setTimeout will never execute unless you exit the do-while loop, which you never do. So you just keep calling first console.log statement then you add a callback to event loop to execute in 1000 ms without ever giving it (the callback that you pass) the chance to execute.

While I would hope the async routines could continue to process during the delays I intended here, I've never seen this loop finish; it's as if the loop takes all processing resources and prevents the async routines from finishing their work and from setting the variable that'll end this loop.

The loop never finish because it doesn't have logic implemented that finishes it. "Async routines" can't continue because that would require exiting the current event frame (that runs infinite loop) and starting the next one that has you callback that you passed to setTimeout.

Hope my explanations will help you to understand how asynchronous JavaScript works.

Upvotes: 1

Joseph
Joseph

Reputation: 119877

JavaScript is single-threaded. setTimeout is not a form of sleep which pauses code at that line. It works by "scheduling" your callback for later, and execute it when the stack exhausts (the engine doing nothing) and is at least n milliseconds later, where n is the delay you placed in milliseconds.

Now your code doesn't work because it never exits the loop. The code doesn't get the chance to execute other code (the code you hope to run and change appMsg.doneLoadTables's value). All it does keep logging "waiting... [something]".

Essentially you are polling. What you could use instead is setInterval. When appMsg.doneLoadTables is true, you stop the polling by using clearInterval.

Upvotes: 4

jpaljasma
jpaljasma

Reputation: 1612

I am not 100% sure what is your goal ... however maybe this snippet takes you where you want to go (I opted for setTimeout instead of setInterval):

var appMsg = {doneLoadTables: false};

var stillLoading = function() {
    if(false === appMsg.doneLoadTables) {
        console.log('waiting ...   ' + appMsg.doneLoadTables);
        setTimeout(stillLoading, 50);
    }
    else {
        console.log('Loading complete.');
        process.exit();
    }
}

stillLoading();
setTimeout(function(){
    console.log('Setting appMsg.doneLoadTables = true');
    appMsg.doneLoadTables = true;
}, 1000);

The script polls status every 50ms and marks "done" exactly after 1 second.

The output looks like this

waiting ...   false
waiting ...   false
waiting ...   false
waiting ...   false
...
Setting appMsg.doneLoadTables = true
Loading complete.

Upvotes: 1

Related Questions