简体   繁体   English

node.js setTimeout()是否正常工作?

[英]Is node.js setTimeout() working?

I'm new to Node.js. 我是Node.js的新手。 Is there something I need to do to get setTimeout() to work? 我需要做些什么才能使setTimeout()工作吗?

Here's a code snippet. 这是一个代码片段。

async code that sets appMsg.doneLoadTables = true when done 完成后将appMsg.doneLoadTables = true设置的异步代码

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. (虽然对console.log的两个调用是相似的,但只有第一个会打印appMsg.doneLoadTables的值。)每个结果都包含该值。
  • The spacing between calls to console.log is much closer than 1000 msec. 两次调用console.log的间隔比1000毫秒小得多。 (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; 我对Node 4.2.1有此经验; I continue to have this experience after installing Node 5.0.0. 安装Node 5.0.0后,我仍然有这种体验。

I've seen that similar questions about setTimeout() have been asked here many times before. 我已经看到关于setTimeout()的类似问题在这里已经问过很多次了。 I hope my use of a IIFE inside setTimeout() makes this question distinct from all of those. 我希望我在setTimeout()中使用IIFE可以使这个问题与所有问题区分开。

Thanks in advance for any help offered ... 在此先感谢您提供的任何帮助...

JavaScript is single-threaded. JavaScript是单线程的。 setTimeout is not a form of sleep which pauses code at that line. setTimeout 不是一种sleep形式,它会在该行暂停代码。 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. 它的工作方式是“安排”回调以供以后使用,并在堆栈耗尽(引擎不执行任何操作)且至少n毫秒后执行时执行,其中n是您放置的延迟(以毫秒为单位)。

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). 该代码没有机会执行其他代码(您希望运行并更改appMsg.doneLoadTables的值的代码)。 All it does keep logging "waiting... [something]". 它所做的全部工作都会记录“正在等待... [某物]”。

Essentially you are polling. 本质上,您正在轮询。 What you could use instead is setInterval . 您可以使用setInterval代替。 When appMsg.doneLoadTables is true , you stop the polling by using clearInterval . appMsg.doneLoadTablestrue ,可以使用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 ): 我不是100%确定您的目标是什么...但是,也许此代码段将您带到了想要去的地方(我选择了setTimeout而不是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. 该脚本每50毫秒轮询一次状态,并在1秒后精确标记为“完成”。

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. (虽然对console.log的两个调用是相似的,但只有第一个会打印appMsg.doneLoadTables的值。)每个结果都包含该值。

That is the correct behavior since you never exit the while loop. 这是正确的行为,因为您永远不会退出while循环。 You stay in the same event frame that keeps looping forever. 您将停留在永远循环的同一事件框架中。

The spacing between calls to console.log is much closer than 1000 msec. 两次调用console.log的间隔比1000毫秒小得多。 (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. 这再次是正确的行为,因为传递给setTimeout的回调将永远不会执行,除非退出从未执行的do-while循环。 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. 因此,您只需继续调用第一个console.log语句,然后将回调添加到事件循环即可在1000毫秒内执行,而不会给它(您传递的回调)执行的机会。

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. “异步例程”无法继续,因为这将需要退出当前事件框架(运行无限循环),并开始下一个将您回调传递给setTimeout的事件框架。

Hope my explanations will help you to understand how asynchronous JavaScript works. 希望我的解释将帮助您了解异步JavaScript的工作方式。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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