Search code examples
javascriptsettimeoutmousemovemouseupcleartimeout

clearTimeout not working on mouseup event


Why is timeout not being cleared in this setup? How can I make up() stop the delayed actions from running?

var active = false;
var delay;

window.addEventListener("mousedown", down, false);
window.addEventListener("mouseup", up, false);
window.addEventListener("mousemove", move, false);

function down(e) {
    active = true;
    console.log("down")
    window.scrollTo(0,document.body.scrollHeight);
}

function up(e) {
    active = false;
    clearTimeout(delay); //expecting this to clear delay
    console.log("up")
    window.scrollTo(0,document.body.scrollHeight);
}

function move(e) {
    if (active) {
        delay = setTimeout(function() {
            console.log("move")
            window.scrollTo(0,document.body.scrollHeight);
        }, 50);
    }
}

Expecting delay to be cleared on mouseup but it still executes.


Solution

  • So, I've learned from the replies that setTimeout produces a new independent timer every time move() is executed. My understanding was that each new timer overwrites the previous one but as this is not the case I had to think of something else.

    I did't really explain what I actually needed to achieve with the delay so let me clarify. I want to create a timeout for an action if that action has not been executed for x amount of time. Using setTimeout on the action it self created the problem that the action would still potentially have multiple queued executions waiting to happen even after mouseup events.

    So instead I used setTimeout on a new variable that acts as a lock to the action. The result is the following code:

    var active = false;
    var actionTimeout = false;
    var actionTimeStamp;
    var actionLock = false;
    
    window.addEventListener("mousedown", down, false);
    window.addEventListener("mouseup", up, false);
    window.addEventListener("mousemove", move, false);
    
    function down(e) {
        active = true;
        console.log("down")
        window.scrollTo(0,document.body.scrollHeight);
    }
    
    function up(e) {
        active = false;
        console.log("up")
        window.scrollTo(0,document.body.scrollHeight);
    }
    
    function move(e) {
        if (active) {
            if ((Date.now() - actionTimeStamp > 500) && (!actionTimeout)) { // get time elapsed and compare to threshold (500ms)
                actionTimeout = true; //this is for the if statement above to prevent multiple timeouts
                actionLock = false; // set the lock
                setTimeout(function() { // remove lock after 50ms
                    actionTimeout = false;
                    actionLock = true;
                    actionTimeStamp = Date.now(); // timestamp here to make sure we don't lock again to soon. (helps if setTimeout is => than threshold.
                }, 50);
            }
            if (actionLock) { //do our action
                console.log("move")
                window.scrollTo(0,document.body.scrollHeight);
                actionTimeStamp = Date.now();  // timestamp last execution
            }
        }
    }
    

    Thanks to everyone for chipping in with comments and answers. Really appreciated.