此示例在演示中给出了期望这些函数的运行顺序为1、2、3,但实际上为1、3、2。很好奇为什么setTimeout函数将最后运行?
console.log(1)
setTimeout(() => console.log(2), 0)
console.log(3)
答案 0 :(得分:1)
异步回调与上面传递给setTimeout()
的回调一样,会在脚本的主要同步主体运行完毕时放入要调用的队列。
所以顺序是:
console.log(1)
setTimeout() // but not the callback
// put callback in queue
console.log(2)
// take item from queue and run
() => console.log(2)
其结果之一是传递给setTimeout
的时间是回调触发前的最短时间。如果主要同步任务花费的时间超过此时间,则回调将延迟触发。
您可以通过运行长时间运行的while
循环来演示这一点。 (但请请不要在真实代码中执行此操作)
let start = Date.now()
let now = start
let then = now + 3000;
// set timer for 100ms
setTimeout(() => console.log("timeout fired ater", Date.now() - start, "milliseconds"), 100)
// slow while loop takes 3000ms
while (now < then){
now = Date.now()
}
console.log("loop done")
答案 1 :(得分:0)
对setTimeout
的回调是异步的,因此它可能已被注册触发*,但是要花足够长的时间才能注册console.log(3)
到那时为止。
在处理异步代码时,您通常不能保证它将以确切的顺序运行。
*老实说,我不知道setTimeout
的内部,这可能取决于反正使用的确切实现。关键是它的回调是异步运行的。