题 setTimeout延迟不起作用


我试图绕过头 setTimeout,但我不能让它正常工作。

我在这里建立了一个例子: http://jsfiddle.net/timkl/Fca2n/

我想要一个文本在点击锚点后倒计时 - 但是我的 setTimeout 似乎同时发射,即使我将延迟设置为1秒。

这是我的HTML:

<a href="#">Click me!</a>

<span id="target"></span>

这是我的JS:

$(document).ready(function() {


function foo(){

    writeNumber = $("#target");

    setTimeout(writeNumber.html("1"),1000);
    setTimeout(writeNumber.html("2"),1000);
    setTimeout(writeNumber.html("3"),1000);
    };

$('a').click(function() {
 foo();
});

});

任何关于我可能做错的提示都非常感谢:)


16
2017-11-19 18:26


起源




答案:


setTimeout 将函数作为参数。您正在执行该函数并将结果传递给 setTimeout (因此该功能立即执行)。您可以使用匿名函数,例如:

setTimeout(function() {
    writeNumber.html("1");
}, 1000);

请注意,情况也是如此 setInterval


39
2017-11-19 18:29



谢谢你的帮助! :)我已经更新了我的jsfiddle: jsfiddle.net/timkl/cRDQh  我仍然得到相同的结果,setTimeouts同时触发。 - timkl
没问题:)如果您不希望它们同时触发,请更改超时长度。例如,第一次超时为1000ms,第二次超时为2000ms,依此类推。 - James Allardice
不仅如此,情况也是如此 setTimeout 和 setInterval,但是对于每种情况,您都应该将回调作为参数之一传递。 - Tadeck
@Tadeck - 是的,好点。执行函数时返回函数:) - James Allardice
@JamesAllardice:同意,但在这种情况下你仍然传递一个回调(即使它是执行另一个函数的结果)。它变得更复杂,但线索是通过 一个功能 我们希望在指定的时间段(或给定的时间间隔)之后执行,而不是在传递时执行它。 - Tadeck


你需要将你的陈述包装在匿名函数中,并且还要错开你的时间 -

setTimeout(function(){writeNumber.html("1")},1000);
setTimeout(function(){writeNumber.html("2")},2000);
setTimeout(function(){writeNumber.html("3")},3000);

如果你把一切都设置为 1000 这些步骤几乎同时运行 setTimeout 函数将在上一次调用之后调用该函数1秒后运行该任务 setTimeout 功能完成。

演示 - http://jsfiddle.net/JSe3H/1/


5
2017-11-19 18:33



+1好点 - 你不仅指出了回调的传递方式,还指出了它的执行方式。 - Tadeck


你需要使用一个功能 参考 在计时器到期后稍后调用。将每个语句包装在匿名函数中,以便它不会立即执行,而是在计时器到期时执行。

setTimeout(function() { writeNumber.html("1"); },1000);

此外,您希望为每个延迟值使用不同的延迟值,以便计时器不会同时到期。看到一个更新的小提琴 http://jsfiddle.net/RqCqM/


2
2017-11-19 18:29





有一个规则可以将参数传递给函数。在你的情况下,你可以做到

setTimeout(writeNumber.html,1000,1);
setTimeout(writeNumber.html,1000,2);
setTimeout(writeNumber.html,1000,3);

setTimeout函数的第三个参数将传递给writeNumber.html函数


2
2017-11-04 15:01





只是用 setInterval()这里这就是我想出来的。这是你的新javascript:

function foo(){
    writeNumber = $("#target");
    number      = 0;
    writeNumber.html(number);
    setInterval(function(){
        number = number+1;
        writeNumber.html(number);
    },1000);
    };
$('a').click(function() {
 foo();
});

1
2017-11-19 18:33





在超时通过后,你需要使用一个函数来调用;你也可以使用匿名函数,那么你的函数foo将如下所示:

function foo(){

writeNumber = $("#target");

setTimeout(function() { writeNumber.html("1"); },1000);
setTimeout(function() { writeNumber.html("2"); },1000);
setTimeout(function() { writeNumber.html("3"); },1000);

};

1
2017-11-19 18:42





我找到了这个问题。它已被充分回答,我认为使用 setInterval 正如@Purag建议的那样,这可能是获得所需功能行为的最佳方法。但是,最初的代码示例并没有考虑JavaScript的异步行为。这是一个经常发生的错误,我已经不止于此了:)。

所以作为附注,我想给出另一个可能的解决方案,模仿初始尝试,但这次考虑Javascript的异步性:

setTimeout(function() {
    writeNumber.html("1");
    setTimeout(function() {
        writeNumber.html("1");
        setTimeout(function() {
            writeNumber.html("1");
        }, 1000);
    }, 1000);
}, 1000);

现在,这显然是可怕的代码!

我给了一个有效的JSFiddle 我自己的问题。这段代码举例说明了所谓的 厄运金字塔。这可以通过使用JavaScript承诺来缓解,如我的问题的答案中所示。编写一个版本需要一些工作 WriteNumber() 使用Promises,然后代码可以重写为somehting,如:

writeNumAsync(0)
    .then(writeNumAsync)
    .then(writeNumAsync)
    .then(writeNumAsync);

0
2017-12-04 20:24