Context variable is reset on zero

I use a node red v1.0.2 docker image for raspberry.
After I adjusted some values for my sensors, I detected some strange behaviour of my functions.
I fiddled around several hours over this problem an can now easily show the problem.

1. create 2 inject nodes with payload true and false
2. connect them to a function node:
var cnt = context.get("cnt") || 3;
if (msg.payload === true) {
cnt += 1;
}
else {
cnt -= 1;
}
context.set("cnt", cnt);
msg.payload = cnt;
return msg;

3. connect a debug node and watch the payload

You will see, that you can increase the counter but not decrease below 0. As soon as the counter reaches 0 it will be initialized with 3.

FCK, I wasted a day of my lifetime over this problem.

Welcome to the forum @sg25.
Look at the line
var cnt = context.get("cnt") || 3;
and consider what it does if context.get("cnt") returns 0.
The || operator means evalute the expression on the left and test it for truthiness. That test returns false for values like false, undefined, empty string and zero. If the test on the left of || returns false then the value on the right of || is returned and assigned to the variable cnt.

And what can you do if you need to have such moving integer is

var cnt = context.get("cnt") 
if(!cnt){
    cnt = 0
}

But you can't have 3 as default if that value is not defined yet.

If you search the forum this exact question comes up often.

Here is one almost identical from less than a day ago...

@Colin.
That is maybe an explanation but an inconvenient and dangerous functionality. Is there any remark about this issue in the documentation?

Normally I initialize variables at the first start of node red before the first real values are triggered by the sensors to prevent unexpected switching actions. A lot of variables are not initialized to zero in my project. If the sensor state changes to zero node red will set the init value, uups... Radio starts playing in the night, the mower is digging thru the snow...what ever.

It is not logical. The context variable is not deleted or undefined. You can see them in the context data browser all the time. The definition || was for me: Take the value from the context memory or, if not defined, initialize with value x. Sorry, but this behaviour should be fixed.

Its a feature of JS language (and very useful when you understand it) & only dangerous if you don't learn how to use it.

I think it's called a short circuit if you wanna look it up.

It is a pain when you need to check for zero (it's because zero is same as false is this case)

Search JavaScript truthiness for more info.

Now I know it. Thank you for the hint.

I used the examples here https://nodered.org/docs/user-guide/writing-functions and I found a lot more examples on the internet using ||.

Before I wrote my message, I searched for node red context variables zero and other phrases in this forum and google. Without success. Maybe it's because of my poor English.

Wow normally I "get a sense" of non English writing... Yours is pretty good. Fooled me.

@Steve-Mcl
Thank you but I sometimes use a translator, write the English version and try to understand the German translation. If this is not successful I'm playing with the words until it fits. That helps to learn better English especially in the age of 62.

To complete the discussion I have corrected the code from above:

var cnt = context.get("cnt");
if (cnt === undefined) {
cnt = 3;
}
if (msg.payload === true) {
cnt += 1;
}
else {
cnt -= 1;
}
context.set("cnt", cnt);
msg.payload = cnt;
return msg;

That works!

2 Likes

It isn't anything to do with context variables, or even node red, it just happens to be useful (often) in this situation. It is much more common to initialise something to zero or an empty array or object or something similar. It is perfectly safe in that situation. The only time it is a problem, the case of numbers, is if the default setting is not zero but zero is a valid value. So all these examples are fine

var x = context.get("x") || 0;
var x = context.get("x") || [ ];
var x = context.get("x") || {};
var x = context.get("x") || false;

but these are not (or are at least risky)

var x = context.get("x") || 3;
var x = context.get("x") || true;

It is just a feature of javascript that one has to know and watch out for.

I have mentioned what I'm thought about ||. I was wrong but now it's clear. Thank you.

I wrote this topic maybe too early. My experience with javascript and node red is only 4 weeks old (pastime in the corona jail). My project, 20 different sensors and 6 cameras, is grown without any problems except this issue.

1 Like

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.