简体   繁体   中英

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:

  • (While the two calls to console.log are similar, only the first prints the value of appMsg.doneLoadTables.) Every result includes that value.
  • 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.)
  • 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.

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 ...

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 .

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.

(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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM