Search code examples
javascriptnode-redhome-assistant

Use clearInterval in NodeRed


I am using NodeRed with Home Assistant. I have a webhook that I can send from a physical device that triggers a function node in node red. The function node looks like this:

var i = 1;

var myTimer = setInterval(function setSlackStatus(){
    if (i < 14){
        var minutesLeft = totalMinutes - [i];

        msg.payload = {
            "profile": {
                "status_text": "Back in " + minutesLeft + " minutes",
                "status_emoji": ":coffee:",
                "status_expiration": 0
            }
        };
        node.send(msg);

        i++;
    } else if (i == 14 ){
        var minutesLeft = totalMinutes - [i];

        msg.payload = {
            "profile": {
                "status_text": "Back in " + minutesLeft + " minute",
                "status_emoji": ":coffee:",
                "status_expiration": 0
            }
        };
        node.send(msg);

        i++;
    } else if (i == 15){
        msg.payload = {
            "profile": {
                "status_text": "I'll be back any second now",
                "status_emoji": ":coffee:",
                "status_expiration": 0
            }
        };
        node.send(msg);

        clearInterval(myTimer);
        i = 1;
    }
}, 60000)

msg.payload = {
    "profile": {
        "status_text": "Back in 15 minutes",
        "status_emoji": ":coffee:",
        "status_expiration": 0
    }
};

if (msg.clearTimer == "true") {
    msg.payload = "Clear Timer signal received.";
    clearInterval(myTimer);
} 

return [msg];

When I send the webhook this function basically loops through a function to update my Slack status once a minute until I get back.

What I'm looking for now is the ability to clear that loop halfway through if needed. So I created a second webhook that sets msg.clearTimer to "true" and then triggers this same node. However, while I get an msg in the debug node that the Clear Timer signal has been received, the function continues to be called on a 1 minute interval until it has run through the entire loop.

What I'm wanting to know is why. Once I've triggered this looping function it seems like there isn't a way to cancel it. Any advice would be greatly appreciated.


Solution

  • Each message is handled independently, so any variables declared and used when the first message arrives in the function node will not exist when the second message arrives (and you would have overwritten the myTimer value anyway at the start of the function)

    If you need things to persist across invocations then you need to store and retrieve them from the context. Documentation about how to use the context in function nodes can be found here.

    As for the task at hand, I'd look using an inject node set to fire a regular intervals, then gate that with a switch node controlled by context variable rather than running a timer in function node.