Reset Timeout of the same timer in a for loop in Javascript

I guess that this could be a duplicate because of the simple nature of the question, but I could not find any answer.

I am setting a Timeout function in a foor loop if a certain condition is true. As I don't want to declare the Timeout within the loop I wrote a setTimeout function to set it outside. I want to use only one timer, which is reset, if it is already running, otherwise the timer should be set the first time. My problem is, that the function sets multiple timers although I am using a clearTimeout().

My code:

    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]);
        }
    }

What I get in the console is:

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

I don't understand why my timer_id is increased every time.

I am passing the id and reset the timer of it. After that I am setting a timer on the same Id, ain't I? Is the reference to the var timeout_id not given and changes it from inside the setTimer function?

Thanks for the help.


将您的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);
};

Question:

I don't understand why my timer_id is increased every time.

I am passing the id and reset the timer of it. After that I am setting a timer on the same Id, ain't I?

Is the reference to the var timeout_id not given and changes it from inside the setTimer function?

Answer:

The reason for to what is happening is that you are passing a primitive number type variable.

Primitive type variables are passed as value and not as a reference.

So in this line ...

setTimer(timeout_id, 900);

... the value of undefined is being passed every time ( not the reference to timeout_id )

and in this line ...

timer_id = setTimeout(function() {

... timer_id is not holding a reference to timeout_id as you are probably expecting.

So what is going on in your setTimer() function:

The first console.log outputs undefined because this is what is passed as parameter.

The second console.log outputs incremented id each time as this is what setTimeout() function returns with each call.

The reason why setTimeOut() returns an incremented unique integer id is that you can stick that id in a variable, so you can use this in future to clear that timeout with clearTimeout( id )

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


Well I found a solution shortly after. By returning the timeout_id and run the function on the timeout_id variable I get only one timer running:

    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]);
        }
    }

Which logs out:

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

You see. Only one timer is finishing after 900ms.

链接地址: http://www.djcxy.com/p/74994.html

上一篇: 侧边栏导航切换与单个按钮

下一篇: 重置Javascript中for循环中同一个定时器的超时时间