2015-11-01 42 views
2

我是Node.js的新手。有什么我需要做的,以setTimeout()工作?是node.js的setTimeout()工作吗?

这是一段代码片段。

异步代码实现

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

症状时,设置appMsg.doneLoadTables =真:

  • (虽然两次调用CONSOLE.LOG是相似的,只有先打印appMsg的价值.doneLoadTables。)每个结果都包含该值。
  • 调用console.log之间的间隔比1000毫秒更接近。 (我怀疑间隔的速度与计算机可以处理此处显示的循环一样快)。
  • 虽然我希望异步例程可以在我期望的延迟期间继续处理,但我从未见过此循环结束;就好像该循环取得所有处理资源并阻止异步例程完成其工作并设置将结束该循环的变量。

我有节点4.2.1的这种经验;在安装Node 5.0.0后,我仍然有这种体验。

我已经看到关于setTimeout()的类似问题已经在这里被问过很多次了。我希望我在setTimeout()中使用IIFE使这个问题与所有这些问题截然不同。

预先感谢您提供的任何帮助...

+0

“我希望我在setTimeout()中使用IIFE使这个问题与所有这些问题截然不同。” - 它没有。 – Quentin

+0

您传递给'setTimeout'的匿名函数不是IIFE,因为它不会立即调用。 – joews

+0

我提出了问题。感谢所有的答案。我更了解async是如何工作的。如果我知道我正在重复以前的问题,我不会提交。这是一个善良和熟练的团队! – BaldEagle

回答

4

JavaScript是单线程的。 setTimeout而不是这是sleep的一种形式,它在该行暂停代码。它通过“调度”你的回调来工作,并在堆栈耗尽时执行它(引擎无所事事),并且至少是n毫秒以后,其中n是以毫秒为单位放置的延迟。

现在你的代码无法工作,因为它永远不会退出循环。代码没有机会执行其他代码(您希望运行的代码并更改appMsg.doneLoadTables的值)。它所有的记录都在“等待...... [某事]”。

基本上你是投票。你可以用什么来代替setInterval。当appMsg.doneLoadTablestrue时,通过使用clearInterval停止轮询。

+0

是的,* setTimeout *是另一种选择。它可以用来保持呼叫,直到满足条件,然后停止拨打电话。 – RobG

1

我不是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); 

脚本轮询状态的时间间隔50ms,并在1秒后标记“完成”。

输出看起来像这样

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

(尽管这两个调用CONSOLE.LOG是相似的,只是第一打印出appMsg.doneLoadTables的值。)每个结果包括该值。

这是正确的行为,因为你永远不会退出while循环。你停留在永久循环的同一事件框架中。

调用console.log之间的间隔比1000毫秒更接近。 (我怀疑的间距是一样快的计算机可以处理此处显示的循环。)

这又是正确的行为,因为你的回调,你传递给setTimeout的会不会执行,除非你退出do-while循环,你永远不会做。所以你只需要继续调用第一个console.log语句,然后在事件循环中添加一个回调,以便在1000毫秒内执行而无需给它(您传递的回调)执行的机会。

尽管我希望异步程序可以在我期望的延迟期间继续处理,但我从未见过这种循环结束;就好像该循环取得所有处理资源并阻止异步例程完成其工作并设置将结束该循环的变量。

循环永远不会完成,因为它没有执行完成的逻辑。 “异步例程”无法继续,因为这需要退出当前事件框架(运行无限循环)并启动下一个将您传递给setTimeout的回调函数。

希望我的解释能帮助你理解异步JavaScript的工作原理。