setTimout() 的 delay 参数在循环中是如何工作的?
How does the delay parameter of setTimout() work within a loop?
我有以下代码,在 for 循环中涉及 IIFE(立即调用函数表达式)。 IIFE 函数显然获得了正确的参数,因为打印输出符合预期。但是我不明白间隔在做什么。据我所知,第一次迭代的间隔应该是 1 秒,然后是第二次迭代的 2 秒,等等
for (var i = 1; i <= 5; i++) {
(function(i){
setTimeout(function timer(){
console.log(i);
}, i*1000);
})(i);
}
我看到 i
以 1 秒为间隔打印为 1..5。这让我感到困惑,因为我期望间隔会随着每次迭代而增加。
使用以下代码:
for (var i = 1; i <= 5; i++) {
(function(i){
setTimeout(function timer(){
console.log(i);
}, 1000);
})(i);
}
我看到 i
的所有值在 1 秒间隔后立即打印出来。
setTimeout 函数中发生了什么使其以观察到的方式工作?
for
循环 运行 秒完成。它不会等待 setTimeout()
调用触发。因此,当 for
循环为 运行ning 时,它会安排 setTimeout()
从现在开始调用 1000、2000、3000、4000、5000 毫秒。因此,您会看到它们都相隔一秒开火。
What is happening within the setTimeout function that is making it
work in the way observed?
setTimeout()
是一个非阻塞的异步操作。它计划在将来运行,但它周围的其他代码继续运行。然后,在未来的某个时候,计时器会触发并调用回调。
所以,您的代码基本上是这样的:
setTimeout(fn, 1000);
setTimeout(fn, 2000);
setTimeout(fn, 3000);
setTimeout(fn, 4000);
setTimeout(fn, 5000);
它 运行 所有 setTimeout()
调用都以非阻塞方式一个接一个地进行。每个 setTimeout()
函数调用只是向底层系统注册一个回调和一个时间,然后下一行代码继续执行。然后,在经过适当的时间后的某个时间,将调用回调。所以,希望你能看到所有的计时器都被安排从现在开始测量它们的时间。因此,您会看到它们每隔 1 秒发射一次。
如果你想类比异步操作,想象一下你在你的房子里走来走去,你设置了五个闹钟在未来的某个时间开始响。你设置一个从现在起一个小时响起,一个从现在起两个小时响起,一个从现在起三个小时响起,等等......然后,你去做其他事情,做午饭,打扫厨房,割草等等。 .. 设置好所有时钟后一小时,第一个闹钟开始响起。一小时后,下一个开始响起,等等......你可以在他们响起之前和之后继续做一些事情。您不必坐下来等待时钟响起再做其他事情。这就是 Javascript 异步定时器操作的样子。您设置它们,然后保留 运行 其他代码,它们会在将来的预定时间触发。
试试这个:
function recursiveTimeout(i) {
setTimeout(function timer(){
console.log(i);
if(i<5) {
recursiveTimeout(i+1);
}
}, 1000 * i);
}
recursiveTimeout(1);
这样下一个 setTimeout 取决于父定时器的结束。
我有以下代码,在 for 循环中涉及 IIFE(立即调用函数表达式)。 IIFE 函数显然获得了正确的参数,因为打印输出符合预期。但是我不明白间隔在做什么。据我所知,第一次迭代的间隔应该是 1 秒,然后是第二次迭代的 2 秒,等等
for (var i = 1; i <= 5; i++) {
(function(i){
setTimeout(function timer(){
console.log(i);
}, i*1000);
})(i);
}
我看到 i
以 1 秒为间隔打印为 1..5。这让我感到困惑,因为我期望间隔会随着每次迭代而增加。
使用以下代码:
for (var i = 1; i <= 5; i++) {
(function(i){
setTimeout(function timer(){
console.log(i);
}, 1000);
})(i);
}
我看到 i
的所有值在 1 秒间隔后立即打印出来。
setTimeout 函数中发生了什么使其以观察到的方式工作?
for
循环 运行 秒完成。它不会等待 setTimeout()
调用触发。因此,当 for
循环为 运行ning 时,它会安排 setTimeout()
从现在开始调用 1000、2000、3000、4000、5000 毫秒。因此,您会看到它们都相隔一秒开火。
What is happening within the setTimeout function that is making it work in the way observed?
setTimeout()
是一个非阻塞的异步操作。它计划在将来运行,但它周围的其他代码继续运行。然后,在未来的某个时候,计时器会触发并调用回调。
所以,您的代码基本上是这样的:
setTimeout(fn, 1000);
setTimeout(fn, 2000);
setTimeout(fn, 3000);
setTimeout(fn, 4000);
setTimeout(fn, 5000);
它 运行 所有 setTimeout()
调用都以非阻塞方式一个接一个地进行。每个 setTimeout()
函数调用只是向底层系统注册一个回调和一个时间,然后下一行代码继续执行。然后,在经过适当的时间后的某个时间,将调用回调。所以,希望你能看到所有的计时器都被安排从现在开始测量它们的时间。因此,您会看到它们每隔 1 秒发射一次。
如果你想类比异步操作,想象一下你在你的房子里走来走去,你设置了五个闹钟在未来的某个时间开始响。你设置一个从现在起一个小时响起,一个从现在起两个小时响起,一个从现在起三个小时响起,等等......然后,你去做其他事情,做午饭,打扫厨房,割草等等。 .. 设置好所有时钟后一小时,第一个闹钟开始响起。一小时后,下一个开始响起,等等......你可以在他们响起之前和之后继续做一些事情。您不必坐下来等待时钟响起再做其他事情。这就是 Javascript 异步定时器操作的样子。您设置它们,然后保留 运行 其他代码,它们会在将来的预定时间触发。
试试这个:
function recursiveTimeout(i) {
setTimeout(function timer(){
console.log(i);
if(i<5) {
recursiveTimeout(i+1);
}
}, 1000 * i);
}
recursiveTimeout(1);
这样下一个 setTimeout 取决于父定时器的结束。