【问题标题】:Reset Timeout of the same timer in a for loop in Javascript在Javascript中的for循环中重置同一计时器的超时
【发布时间】:2016-07-30 17:19:04
【问题描述】:

由于问题的简单性质,我猜这可能是重复的,但我找不到任何答案。

如果某个条件为真,我将在 foo 循环中设置超时函数。因为我不想在循环中声明超时,所以我编写了一个 setTimeout 函数将其设置在外部。 我只想使用一个计时器,如果它已经在运行,它会被重置,否则应该第一次设置计时器。 我的问题是,尽管我使用的是 clearTimeout(),但该函数设置了多个计时器。

我的代码:

    var timeout_id;
    var things = [true, true, false, true, true];

    var setTimer = function(timer_id, duration) {
        console.log("timer_id: ", timer_id);
        // clear timeout of the given Id
        clearTimeout(timer_id);
        timer_id = setTimeout(function() {
            // reset flag
            console.log("Timer timed out");
        }, duration);
        console.log("timer_id: ", timer_id);
    };

    for (var i = things.length - 1; i >= 0; i--) {
        if (things[i]) {
            setTimer(timeout_id, 900);
            console.log("Timer set because value of : " + i + " = ", things[i]);
        }
    }

我在控制台中得到的是:

timer_id:  undefined
timer_id:  1
Timer set because value of : 4 =  true
timer_id:  undefined
timer_id:  2
Timer set because value of : 3 =  true
timer_id:  undefined
timer_id:  3
Timer set because value of : 1 =  true
timer_id:  undefined
timer_id:  4
Timer set because value of : 0 =  true
timer timed out
timer timed out
timer timed out
timer timed out

我不明白为什么我的 timer_id 每次都增加。

我正在传递 id 并重置它的计时器。之后,我在同一个 ID 上设置了一个计时器,不是吗? 是否没有给出对 var timeout_id 的引用并从 setTimer 函数内部对其进行更改?

感谢您的帮助。

【问题讨论】:

  • 您将 'timer_id' 传递给函数,并将其设置为 setTimeout(...) 您不想使用外部范围的变量 'timeout_id' 吗?
  • 我不想这样,因为我想在不同的计时器变量上调用 setTimer 函数。但是请检查我的答案。我想我在那里找到了解决方案。

标签: javascript loops for-loop settimeout cleartimeout


【解决方案1】:

我很快就找到了解决方案。 通过返回 timeout_id 并在 timeout_id 变量上运行函数,我只运行了一个计时器:

    var timeout_id;
    var things = [true, true, false, true, true];

    var setTimer = function(timer_id, duration) {
        console.log("timer_id: ", timer_id);
        // clear timeout of the given Id
        clearTimeout(timer_id);
        timer_id = setTimeout(function() {
            // reset flag
            console.log("Timer timed out");
        }, duration);
        console.log("timer_id: ", timer_id);
        return timer_id;
    };

    for (var i = things.length - 1; i >= 0; i--) {
        if (things[i]) {
            timeout_id = setTimer(timeout_id, 900);
            console.log("Timer set because value of : " + i + " = ", things[i]);
        }
    }

退出:

timer_id:  undefined
timer_id:  1
Timer set because value of : 4 =  true
timer_id:  1
timer_id:  2
Timer set because value of : 3 =  true
timer_id:  2
timer_id:  3
Timer set because value of : 1 =  true
timer_id:  3
timer_id:  4
Timer set because value of : 0 =  true
Timer timed out

你看。只有一个计时器在 900 毫秒后完成。

【讨论】:

    【解决方案2】:

    将您的 setTimer 函数更改为:

    var timer_ids = {};
    
    var setTimer = function(timer_id, duration) {
        console.log("timer_id: ", timer_id);
        // clear timeout of the given Id
        clearTimeout(timer_ids[timer_id]);
        timer_ids[timer_id]= setTimeout(function() {
            // reset flag
            console.log("Timer timed out");
        }, duration);
        console.log("timer_id: ", timer_id);
    };
    

    【讨论】:

    • 嗯,这也是我的第一种方法,但是因为我希望至少有两个计时器(它们应该同时运行),所以我肯定想用不同的 ID 调用 setTimer 函数两次。假设我有一个计时器在点击后重置计时器,在悬停后重置计时器。我需要不同的计时器,我想调用 setTimer(first_timer_id);和 setTimer(sec_timer_id);都在一个 for 循环中,这就是为什么我想在必要时重置每一个......
    • 哦,那么你可以把 timeout_id 放在一个 hashmap(json 对象)中,其中键是你的“计时器”id,值是 timeout_id - 就像这样: clearTimeout(timerIds[timerId] ); timerIds[timerId] = setTimeout()..:;其中 timerIds 是 setTimer 函数范围之外的变量,我会更新我的答案。
    • 酷。那很好。我也遇到了一些上下文问题,因为我的 setTimer 函数是一个单独的 «class» 的私有函数。所以 this 不是我所期望的 this 并且也会造成一些麻烦:)。不管怎么说,还是要谢谢你。它解决了我的问题。
    【解决方案3】:

    问题:

    我不明白为什么我的 timer_id 每次都增加。

    我正在传递 id 并重置它的计时器。之后我设置 同一个 ID 上的计时器,不是吗?

    是对var的引用 未给出 timeout_id 并从 setTimer 函数内部对其进行更改?

    答案:

    发生这种情况的原因是您传递了一个 primitive 数字类型变量。

    原始类型变量作为值而不是引用传递。

    所以在这一行...

    setTimer(timeout_id, 900);
    

    ... undefined 的值每次都被传递(不是对 timeout_id 的引用)

    在这一行...

    timer_id = setTimeout(function() {
    

    ... timer_id 没有像您预期的那样持有对 timeout_id 的引用。

    那么你的 setTimer() 函数中发生了什么:

    第一个 console.log 输出 undefined 因为这是作为参数传递的内容。

    第二个 console.log 每次都会输出递增的 id,因为这是 setTimeout() 函数在每次调用时返回的内容。

    setTimeOut() 返回一个递增的唯一整数 id 的原因是您可以将该 id 保存在一个变量中,因此您可以在将来使用它来清除 clearTimeout( id ) 的超时

    Here is a nice explanation of 'Passing by Value or by Reference'

    【讨论】:

    • 感谢分享。没有,这没有作为参考传递。你永远不会停止学习。谢谢
    • *不知道(无法编辑我的评论以更正错字...)
    • 没问题知道这样的事情是很好的,以避免将来出现类似的问题。只是向anwser添加了更多解释。我希望它有所帮助。 :)
    猜你喜欢
    • 1970-01-01
    • 2021-11-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-19
    相关资源
    最近更新 更多