为什么我的setTimeout回调没有被调用?

时间:2017-11-18 10:37:36

标签: javascript jquery timer

我正在忙着建立一个闪存卡游戏。我希望在卡片在屏幕上闪烁之前给用户一个可见的倒计时。我的倒计时脚本如下所示:

let downSeconds = 5;
while (downSeconds > 0) {
    setTimeout(function() {
        $("#timerDisplay").text = downSeconds;
        downSeconds--;
    }, 1000);
}

$(".detail-card").removeClass("hidden");

如果我不想要更新的秒数,我只需要使用5000毫秒的setTimeOut'。我在尝试使用setInterval之前做了一次,延迟时间为1000毫秒,因此每次过去都会更新秒数。

现在,如果我在setTimeOut回调的任一行放置一个断点,并且仅在那里,在调用setTimeout时没有任何反应,因此秒显示永远不会更新,而且我' m在无限循环中,因为永远不会调用downSeconds--;,所以downSeconds始终保持值为5。

我做错了什么?

3 个答案:

答案 0 :(得分:1)

setTimeout稍后运行代码,而while循环运行“now”。你不能成功地将两者结合起来。所以,你必须以不同的方式编写你的代码,这样的事情应该有效:

let downSeconds = 5;
function doCountDown() {
    downSeconds--;
    $("#timerDisplay").text = downSeconds;
    if (downSeconds > 0) {
        setTimeout(doCountDown, 1000);
    } else {
        $(".detail-card").removeClass("hidden");
    }
}
setTimeout(doCountDown, 1000);

答案 1 :(得分:1)

您可以使用ES7并等待循环一秒钟:

const time = ms => new Promise(res => setTimeout(res,ms));

(async function(){
   let downSeconds = 5;
   while (downSeconds > 0) {
    await time(1000);
    $("#timerDisplay").text = downSeconds;
    downSeconds--;
   }
   $(".detail-card").removeClass("hidden");
})()

答案 2 :(得分:1)

setTimeout调用是异步的, 因此,当第一次调用setTimeout所计划的1000毫秒过去时, while循环将执行其身体数千次, 每次使用setTimeout安排新工作时, 导致JavaScript引擎的大量调度工作。 引擎太忙而无法执行该功能, 而且它一直在恶化, 因为循环继续运行并且越来越多地保持调度。 我希望您的执行环境变得无法响应,无法取得进展,无法实际调用第一个已安排的函数。

改为使用setIntervalclearInterval,例如:

let counter = 5;
let interval = setInterval(() => {
    $("#timerDisplay").text = counter;
    counter--;
    if (counter == 0) {
        clearInterval(interval);
        $(".detail-card").removeClass("hidden");
    }
}, 1000);