setTimeout开始倒计时的时间是什么时候?

4
这是我现在正在使用的代码:
setTimeout(() => console.log('first'), 2000);
for (let i  = 0; i < 5000; i++) {
   console.log("printing...")
}
setTimeout(() => console.log('second'), 1000);

期望(setTimeout立即开始倒计时)

  1. 第一个setTimeout将执行并启动2000毫秒的计时器。然而,由于setTimeout回调是异步运行的,我们必须跳过它并等待整个调用堆栈完成后再处理回调队列。
  2. 遍历for循环。从我的计算机上看,整个for循环大约需要20秒才能完成运行。在for循环的几秒钟后,第一个setTimeout应该已经完成了计时器。
  3. 然后执行第二个setTimeout并启动计时器。与第一步类似。
  4. 现在调用堆栈已经运行完毕,我们遍历回调队列。由于第一个setTimeout应该先完成延迟,尽管延迟更长,它应该先打印"first"然后是"second"

实际情况

printing...
/* Lots of "printing..." strings */
printing...
second
first

似乎情况是第二个 setTimeout 仍然先运行。这种情况下,这是否意味着 setTimeout 的倒计时只在初始几行代码运行后开始?我在 Firefox 和 Chrome 上测试了这段代码,它们似乎有相同的行为。

3
是的,第二个超时先运行,它比第一个超时提前大约一秒钟。倒计时在setTimeout执行后立即开始。请注意,迭代一个长度为5000的循环只需要几毫秒的时间。 - undefined
2
我看不出for (let i = 0; i < 5000; i++) { console.log("printing...") }需要20秒的原因。可能是打印的过程需要时间,但这并不意味着循环需要20秒。 - undefined
1
所以,澄清一下,for循环实际上已经完成了,只是将字符串打印到控制台需要很长时间吗?在JSFiddle上运行代码对我来说需要相当长的时间才能完成for循环,但如果延迟只是在打印上,那就说得通了。作为后续问题,这是否意味着如果有两个setTimeout,它们之间的代码运行时间足够长,第一个setTimeout(假设它的延迟时间比第二个长)在第二个之前打印出来是可能的吗? - undefined
1
@seeingstars 看起来是这样的。你可以通过将Date()作为第二个参数添加到你的console.log调用中来验证 - 这将在代码执行时运行,无论之后打印多久。 - undefined
2
在JSFiddle上运行代码对我来说需要相当长的时间才能完成for循环。不,循环本身完成得相当快。然而,打印输出需要更长时间。你可能正在查看页面上的控制台。在这里的“打印输出”意味着更新DOM,这比实际控制台要花费更多的时间。你实际上没有测量到正确的事情- DOM更新不是代码的实际执行内容。打开你的浏览器控制台来看看区别。https://jsfiddle.net/0hy7qr1n/ - undefined
显示剩余9条评论
1个回答

2
你的期望是正确的,但是提供的示例是误导性的。for循环不会花费大约20秒的时间。JavaScript会更快地完成。可能需要JavaScript容器(比如你的浏览器)大约20秒的时间来打印所有内容,但是脚本会继续执行下去。

//    [------ unit definition ------]  [--------- alias --------]
const MILLISECOND =    1             , MILLISECONDS = MILLISECOND;
const SECOND      = 1000*MILLISECONDS, SECONDS      = SECOND     ;

setTimeout(() => console.log('first'), 2*SECONDS);

console.log("starting heavy work");
const start = Date.now();
for (let i  = 0; i < 5000; i++) {
   console.log("printing...");
}
console.log(`finished work in ${(Date.now() - start)/SECONDS}s`);

setTimeout(() => console.log('second'), 1*SECOND);

setTimeout(() => console.log('second'), 1*SECOND)setTimeout(() => console.log('first'), 2*SECONDS)之后不到一秒钟执行。通过比较循环的开始时间和结束时间,您可以看到循环实际上需要多长时间。

这是一个实际上忙碌了大约5秒钟的代码示例。

//    [------ unit definition ------]  [--------- alias --------]
const MILLISECOND =    1             , MILLISECONDS = MILLISECOND;
const SECOND      = 1000*MILLISECONDS, SECONDS      = SECOND     ;


setTimeout(() => console.log("first"), 2*SECONDS);

console.log("starting heavy work");
const start = Date.now();
while (Date.now() - start < 5*SECONDS); // block the script for 5 seconds
console.log(`finished work in ${(Date.now() - start)/SECONDS}s`);

setTimeout(() => console.log("second"), 1*SECOND);


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接