setTimeout在Node.js中等待太长时间

Sea*_*dre 1 javascript asynchronous settimeout node.js

我想我对setTimeoutJavaScript的确切含义有误解.我有这个脚本:

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));
Run Code Online (Sandbox Code Playgroud)

我期望发生的是recursiveFibonacci开始在斐波那契序列中的第43个值上开始.这在我的电脑上大约需要4秒钟.因此,在1秒钟的工作后,评估将被中断,控制台将记录:

one second
Run Code Online (Sandbox Code Playgroud)

然后约3秒后登录:

433494437
Run Code Online (Sandbox Code Playgroud)

相反,发生的事情是,在4秒后,控制台记录:

433494437
one second
Run Code Online (Sandbox Code Playgroud)

一次全部.为什么会这样?我怎么setTimeout去上班?是这样的情况,JavaScript解释器实际上并没有被中断, setTimeout而是如果它完成其他工作,那么它将等到给定的时间量已经过去,然后再调用给定的函数?

编辑:

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

放大镜

jfr*_*d00 6

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

因此,即使计时器触发并且计时器回调被放入内部nodejs事件队列,JS解释器也无法到达事件队列中的下一个事件,直到您的reverseFibonacci()函数完成.

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

因此,您的方案中的事件顺序如下:

  1. 从现在起安排计时器事件1秒钟.
  2. 开始跑步 reverseFibonacci()
  3. Timer在1秒后触发(在nodejs内部)并将事件插入nodejs事件队列.
  4. 4秒后,您的reverseFibonacci(42)完成运行.
  5. 由于当前运行的JS已经完成,JS解释器将下一个事件拉出事件队列并对其进行处理,从而导致最终调用计时器回调.

定时器setTimeout()在预定时间之后尽快安排运行,但如果Javascript解释器忙于运行其他代码,则它们不会中断该代码.计时器系统将一个事件放入事件队列中,当完成其他代码时,Javascript解释器将把下一个事件拉出事件队列并运行它(你的计时器回调将被调用).