node.js setTimeout()是否有效?

时间:2015-11-01 20:38:41

标签: javascript node.js

我是Node.js的新手。我需要做些什么来让setTimeout()工作吗?

这是一个代码段。

完成后设置appMsg.doneLoadTables = true的异步代码

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

症状:

  • (虽然对console.log的两次调用是相似的,但只有第一次打印appMsg.doneLoadTables的值。)每个结果都包含该值。
  • 对console.log的调用之间的间隔远小于1000毫秒。 (我怀疑间距和计算机处理此处显示的循环的速度一样快。)
  • 虽然我希望异步例程可以在我打算延迟的过程中继续处理,但我从未见过这个循环完成;这就好像循环占用了所有处理资源并阻止异步例程完成它们的工作以及设置将结束此循环的变量。

我有Node 4.2.1的经验;我在安装Node 5.0.0后继续有这方面的经验。

我已经看到过类似的关于setTimeout()的问题之前已经多次被问过了。我希望我在setTimeout()中使用IIFE可以使这个问题与所有这些问题区别开来。

提前感谢您提供的任何帮助......

3 个答案:

答案 0 :(得分:4)

JavaScript是单线程的。 setTimeout sleep的一种形式,它会暂停该行的代码。它的工作原理是"调度"稍后回调,并在堆栈耗尽(引擎什么都不做)时执行它,并且至少n毫秒后,n是您放置的延迟(以毫秒为单位)。

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

基本上你是在投票。您可以使用的是setInterval。当appMsg.doneLoadTablestrue时,您可以使用clearInterval停止投票。

答案 1 :(得分: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.

答案 2 :(得分:1)

  

(虽然对console.log的两次调用是相似的,但只有第一次打印appMsg.doneLoadTables的值。)每个结果都包含该值。

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

  

对console.log的调用之间的间隔远小于1000毫秒。 (我怀疑间距与计算机处理此处显示的循环一样快。)

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

  

虽然我希望异步例程可以在我想要的延迟期间继续处理,但我从未见过这个循环完成;这就好像循环占用了所有处理资源并阻止异步例程完成它们的工作以及设置将结束此循环的变量。

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

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