在Node.js中,setTimeout等待时间过长

我想我有一个误解的是什么setTimeout完全在JavaScript中。 我有这个脚本:

 function recursiveFibonacci(n) { if ( n === 0 ) { return 1; } else if ( n === 1 ) { return 1; } else { return recursiveFibonacci(n-1) + recursiveFibonacci(n-2); } } setTimeout( () => {console.log("one second");}, 1000); console.log(recursiveFibonacci(42)); 

我期望发生的事情是,recursion斐波纳契开始突破斐波那契数列中的第43个值。 我的电脑需要4秒左右的时间。 所以,工作1秒后,评估将会中断,控制台将logging:

 one second 

然后约3秒钟后login:

 433494437 

相反,在4秒后,控制台会logging:

 433494437 one second 

一次全部。 这是为什么? 我怎样才能让setTimeout工作? 是否这样的情况是JavaScript解释器实际上并没有被setTimeout中断,而是如果它完成了其他的工作,那么它会等到给定的函数调用给定的时间之前已经过去了一段时间?

编辑:

我发现这个工具对于理解相关概念非常有用:

放大镜

node.js中的Javascript是事件驱动和单线程的。 由于您的reverseFibonacci()函数是同步的,因此在完成之前不允许其他任何内容运行。

因此,即使定时器触发并且定时器callback被放入内部nodejs事件队列,JS解释器也不能到达事件队列中的下一个事件,直到你的reverseFibonacci()函数完成。

setTimeout()不会中断当前正在运行的Javascript。 相反,它将事件放入事件队列中,当当前正在运行的Javascript完成时,JS解释器将把下一个事件从事件队列中拉出并运行。

所以,在你的情况下事件的顺序是这样的:

  1. 从现在开始计划1秒的计时器事件。
  2. 开始运行reverseFibonacci()
  3. 定时器在1秒钟后触发(在nodejs中),并将事件插入到nodejs事件队列中。
  4. 4+秒后,您的reverseFibonacci(42)完成运行。
  5. 由于当前正在运行的JS已经完成,JS解释器将下一个事件拉出事件队列并对其进行处理,导致您的计时器callback最终被调用。

setTimeout()定时器计划在预定时间后尽快运行,但是如果Javascript解释器忙于运行其他代码,则不会中断该代码。 定时器系统把一个事件放到事件队列中,当其他代码完成时,Javascript解释器将把下一个事件从事件队列中拉出来并运行(你的定时器callback将被调用)。

这是因为你的function同步工作。

节点事件循环的本质是asynchronous的。 至于你的function完成执行或者你会执行一些asynchronous – nextTick将被调用。 而最有可能的第一个项目将是你setTimoutfunction。

以下是预期的asynchronous块的例子,它可以像你期望的那样工作:

 function sleep(ms) { return new Promise( (resolve, reject) => { setTimeout(resolve, ms); }); } async function recursiveFibonacci(n) { await sleep(10); if ( n === 0 ) { return 1; } else if ( n === 1 ) { return 1; } else { return await recursiveFibonacci(n-1) + await recursiveFibonacci(n-2); } } setTimeout( () => {console.log("one second");}, 1000); recursiveFibonacci(25).then(console.log);