循环内的 setTimeout() 方法
Posted
技术标签:
【中文标题】循环内的 setTimeout() 方法【英文标题】:setTimeout() method inside a while loop 【发布时间】:2016-10-10 05:42:26 【问题描述】:我已经阅读了关于 w3schools 的相关页面和其他类似问题,但似乎无法理解以下内容有什么问题:
var myfunc03 = function (i)
document.getElementById('d01').innerhtml += 100-i+"<br>";
;
var myFunc01 = function()
i=0;
while (i<100)
setTimeout(myfunc03(i), 1000)
i++;
;
当myFunc01();
运行时。
没有任何停顿,i 的所有可能值都会立即列出。
这里有逻辑错误吗?
【问题讨论】:
这当然突出了他的第二个错误——从闭包中访问修改后的变量 (i
)。当超时触发时,i
将更改为最后一个。
setTimeout
期望 Function
作为第一个参数,但您传递的是 myfunc03
的 result (这是 underfined
,因为您正在调用它)
【参考方案1】:
while
循环不会等待 setTimeout()
完成。您需要为每个设置不同的时间延迟以在不同的时间执行它们,并使用闭包来保存i
的值。同样在您的情况下,函数将首先执行,并且返回值设置为 setTimeout()
中的参数,因此您需要在匿名函数中调用该函数或直接设置该函数。
var myFunc01 = function()
var i = 0;
while (i < 100)
(function(i)
setTimeout(function()
document.getElementById('d01').innerHTML += 100 - i + "<br>";
, 1000 * i)
)(i++)
;
myFunc01();
<span id="d01"></span>
虽然这里可以使用
setInterval()
var myFunc01 = function()
var i = 0;
// store the interval id to clear in future
var intr = setInterval(function()
document.getElementById('d01').innerHTML += 100 - i + "<br>";
// clear the interval if `i` reached 100
if (++i == 100) clearInterval(intr);
, 1000)
myFunc01();
<span id="d01"></span>
【讨论】:
详尽的解释。我遇到了同样的问题。很好的例子,谢谢!【参考方案2】:您可以使用递归更简单做到这一点:
var i = 0;
function f1() ... ;
function f()
f1();
i += 1;
setTimeout(function()
if(i < 100)
f();
, 1000);
f();
示例
var i = 0;
var myfunc03 = function(i)
document.getElementById('d01').innerHTML += 100 - i + "<br>";
;
var myFunc01 = function()
myfunc03(i);
i += 1;
setTimeout(function()
if (i < 100)
myFunc01();
, 1000);
myFunc01();
<div id="d01"></div>
一个可重用的函数
function say(sentence)
console.log(sentence);
function sayHello()
say("Hello!");
var fn = sayHello;
var count = 10;
var ms = 1000;
function repeat(fn, count, ms)
var i = 0;
function f()
fn();
i += 1;
setTimeout(function()
if (i < count)
f();
, ms);
f();
repeat(fn, count, ms);
【讨论】:
【参考方案3】:while
等待setTimeout
:
(async () =>
var i = 0;
while (await new Promise(resolve => setTimeout(() => resolve(i++), 1000)) < 100)
console.log("I get printed 100 times every second");
)();
【讨论】:
【参考方案4】:是的。您的代码中有两个问题:
-
setTimeout 函数接受一个函数作为第一个参数,但在您的代码中,
myfunc03(i)
不返回任何内容
while 循环不能满足你的需要,你必须使用递归函数。因为第二个函数应该在第一个超时触发后调用。
示例代码:
var myfunc03 = function (i)
setTimeout(function()
document.getElementById('d01').innerHTML += 100-i+"<br>";
if (i < 100)
i++;
myfunc03(i);
, 1000);
;
var myFunc01 = function()
myfunc03(0);
;
myFunc01();
<div id="d01"></div>
【讨论】:
【参考方案5】:我认为您在 setTimeout 上缺少分号,您应该尝试按以下方式传递参数:
setTimeout(myfunc03, 1000*i, i);
【讨论】:
对于现代浏览器来说,这是最好的解决方案,因为它避免了闭包的尴尬。但是,第二个参数应该是1000 * i
;否则,您同时将 100 个超时设置为 1 秒。比较 jsfiddle.net/ofpp26or/2 和 jsfiddle.net/ofpp26or
是的,没错。我打算只显示语法,因为这可能会导致 js 错误。他可能会根据他的逻辑要求使用时间参数。【参考方案6】:
一个简单的选择是改用setInterval()
方法。
setInterval 将每次循环执行代码,直到您使用 clearInterval()
方法将其中断。
示例:
var index = 0;
let incrementEveryHalfSecond = setInterval(function()
index++;
document.querySelector("body").innerHTML += index+'</br>';
if(index == 10) clearInterval(incrementEveryHalfSecond)
, 500)
<body></body>
请注意,您决定中断循环,将存储 setInterval 方法的变量作为参数传递给 clearInterval 方法。现在您可以创建函数以获得更好的清晰代码。 w3schools documentation
问题回答:[从 100 到 1] 我倒了 i 的顺序来简化,但你也可以使用“100-i
”。
var myfunc03 = function (i)
document.getElementById('d01').innerHTML += i+"<br>";
;
var myFunc01 = function()
let i=100;
let incrementEveryOneSecond = setInterval(function()
myfunc03(i);
if(--i == 0) clearInterval(incrementEveryOneSecond);
, 1000)
;
myFunc01();
<span id="d01"></span>
【讨论】:
【参考方案7】:while 方法运行速度很快,所有超时几乎都在第一秒后执行。你可以做的是
-
而不是 while 从
myfunc03
调用 $timeout
以获得下一个值
在您的 while 呼叫超时内,随着秒数的增加,例如 i*1000
另外,正如其他人指出的那样,您不能使用来自 setTimeout
的参数调用函数
使用匿名函数,如
...
while (i<100)
setTimeout(
function(i)
myfunc03(i);
, i*1000);
i++;
...
为此
【讨论】:
请继续努力。这既不可读也不可理解 @mplungjan 是的,我的错! 您没有解决关闭问题 我知道,其他人已经这样做了,最初我错过了。所以我只是修改了我原来的答案。抄袭别人的答案感觉不对:) @mplungjan 没关系。我不只是为了选票或声誉而写东西。只是消磨一些空闲时间并帮助其他编码人员:) 无论如何,按照你的坚持纠正答案以上是关于循环内的 setTimeout() 方法的主要内容,如果未能解决你的问题,请参考以下文章
JavaScript:了解 for 循环内的 let 范围 [重复]
Javascript中setTimeout()以及clearTimeout( )的使用
JS里设定延时:js中SetInterval与setTimeout用法
js的事件循环机制:同步与异步任务(setTimeout,setInterval)宏任务,微任务(Promise,process.nextTick)