Javascript: decide about multiple vars - any idea how maintain it more easy?

I have around six vars. Depending on their condition (true/false) I have to return something.

Should I do it that way:
if (msg.payload.on == true && global.get("Var") == true && ...) { }

or

if (msg.payload.on == true) {
 if (global.get("Var") == true) {
  if (..) {
}
}
}

or is there another way i do not know?

I tried both, but after some months I every time need ages to find the correct entry to modify.

There is also "return early" code design pattern. Do search world wide..

If the values are always true or false then you don't need to test for equality with true. You can use
if (msg.payload.on && global.get("Var") && ...) { }
The difference is that if the variable is not a boolean then you may get a 'true' answer. For example any non-zero number would be treated as true, any string would be true, and so on. If one of the tests is for not true then use && !somevar &&

If in your brain the way you think about is is "if this is true and that is true etc" then you should code it using a single if. If in your brain you think "if this is true then we need to test that and if that is true then test something else, then you should use your second option. Generally you should code it the way that best reflects the problem you are trying to solve. That way you are least likely to make mistakes in the code.

Don't worry about the efficiency of the code. Unless you are executing it thousands of times a second it will make no detectable difference.

1 Like

I would create a JS object which contains all properties as booleans. Putting this object into a change of function node, you can check the properties with AND or OR.

OR.´:

var x;
var obj = msg.payload;
var bIsBoolean=false;
 
for (x in obj) {
  bIsBoolean = bIsBoolean || obj[x];
  
}
 
msg.payload=bIsBoolean;
return msg;

AND:

var x;
var obj = msg.payload;
var bIsBoolean=true;
 
for (x in obj) {
  bIsBoolean = bIsBoolean && obj[x];
  
}
 
msg.payload=bIsBoolean;
return msg;

or as I said you put your JS object into a switch or change node. Here are my nodes, I use in my local libary:

Zusammenfassung
[
    {
        "id": "225fdcf0.030744",
        "type": "switch",
        "z": "54b226bc.0793e8",
        "name": "AND?",
        "property": "$reduce(payload.*,function($i, $j){$i and $j})",
        "propertyType": "jsonata",
        "rules": [
            {
                "t": "true"
            },
            {
                "t": "false"
            }
        ],
        "checkall": "true",
        "repair": false,
        "outputs": 2,
        "x": 470,
        "y": 3200,
        "wires": [
            [],
            []
        ],
        "info": "# All properties of an object must be true.\n\nAll properties of an object must be true.\n\n`{\n    \"Office\": true,\n    \"Bedroom\": true,\n    \"Living Room Balcony\": true,\n    \"Living Room Right Window\": true,\n    \"Living Room Left Window\": true\n}`\n\nis true,\n\n`{\n    \"Office\": true,\n    \"Bedroom\": false,\n    \"Living Room Balcony\": true,\n    \"Living Room Right Window\": true,\n    \"Living Room Left Window\": true\n}`\n\nis false.\n\n# Alle Eigenschaften eines Objektes müssen wahr sein\n\nAlle Eigenschaften eines Objektes müssen wahr sein.\n\n`{\n    \"Büro Balkon\": true,\n    \"Schlafzimmer Balkon\": true,\n    \"Wohnzimmer Balkon\": true,\n    \"Wohnzimmer rechtes Fenster\": true,\n    \"Wohnzimmer linkes Fenster\": true\n}`\n\nergibt true,\n\n`{\n    \"Büro Balkon\": true,\n    \"Schlafzimmer Balkon\": true,\n    \"Wohnzimmer Balkon\": true,\n    \"Wohnzimmer rechtes Fenster\": false,\n    \"Wohnzimmer linkes Fenster\": true\n}`\n\nergibt false."
    },
    {
        "id": "2a274afb.2f7d76",
        "type": "change",
        "z": "54b226bc.0793e8",
        "name": "AND ?",
        "rules": [
            {
                "t": "set",
                "p": "payload",
                "pt": "msg",
                "to": "$reduce(payload.*,function($i, $j){$i and $j})",
                "tot": "jsonata"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 470,
        "y": 3240,
        "wires": [
            []
        ],
        "info": "# All Property of an object must be true.\n\nAll properties of an object must be true.\n\n`{\n    \"Office\": true,\n    \"Bedroom\": true,\n    \"Living Room Balcony\": true,\n    \"Living Room Right Window\": true,\n    \"Living Room Left Window\": true\n}`\n\nis true,\n\n`{\n    \"Office\": true,\n    \"Bedroom\": false,\n    \"Living Room Balcony\": true,\n    \"Living Room Right Window\": true,\n    \"Living Room Left Window\": true\n}`\n\nis false.\n\n# Alle Eigenschaften eines Objektes müssen wahr sein\n\nAlle Eigenschaften eines Objektes müssen wahr sein.\n\n`{\n    \"Büro Balkon\": true,\n    \"Schlafzimmer Balkon\": true,\n    \"Wohnzimmer Balkon\": true,\n    \"Wohnzimmer rechtes Fenster\": true,\n    \"Wohnzimmer linkes Fenster\": true\n}`\n\nergibt true,\n\n`{\n    \"Büro Balkon\": true,\n    \"Schlafzimmer Balkon\": true,\n    \"Wohnzimmer Balkon\": true,\n    \"Wohnzimmer rechtes Fenster\": false,\n    \"Wohnzimmer linkes Fenster\": true\n}`\n\nergibt false."
    },
    {
        "id": "3a1e5265.93622e",
        "type": "switch",
        "z": "54b226bc.0793e8",
        "name": "OR?",
        "property": "$reduce(payload.*,function($i, $j){$i or $j})",
        "propertyType": "jsonata",
        "rules": [
            {
                "t": "true"
            },
            {
                "t": "false"
            }
        ],
        "checkall": "true",
        "repair": false,
        "outputs": 2,
        "x": 630,
        "y": 3200,
        "wires": [
            [],
            []
        ],
        "info": "# Only one or more properties of an object need to be true.\n\n Only one or more properties of an object need to be true.\n\n`{\n    \"Office\": false,\n    \"Bedroom\": false,\n    \"Living Room Balcony\": false,\n    \"Liviueng Room Right Window\": false,\n    \"Living Room Left Window\": false\n}`\n\nis false,\n\n`{\n    \"Office\": false,\n    \"Bedroom\": true,\n    \"Living Room Balcony\": false,\n    \"Living Room Right Window\": false,\n    \"Living Room Left Window\": false\n}`\n\nis true.\n\n# Mindestens eine Eigenschaft des Objektes muss wahr sein.\n\nMindestens eine Eigenschaft des Objektes muss wahr sein.\n\n`{\n    \"Büro Balkon\": false,\n    \"Schlafzimmer Balkon\": false,\n    \"Wohnzimmer Balkon\": false,\n    \"Wohnzimmer rechtes Fenster\": false,\n    \"Wohnzimmer linkes Fenster\": false\n}`\n\nergibt false,\n\n`{\n    \"Büro Balkon\": false,\n    \"Schlafzimmer Balkon\": true,\n    \"Wohnzimmer Balkon\": false,\n    \"Wohnzimmer rechtes Fenster\": false,\n    \"Wohnzimmer linkes Fenster\": false\n}`\n\nergibt true (wahr)."
    },
    {
        "id": "f3066bc6.8bf028",
        "type": "change",
        "z": "54b226bc.0793e8",
        "name": "OR ?",
        "rules": [
            {
                "t": "set",
                "p": "payload",
                "pt": "msg",
                "to": "$reduce(payload.*,function($i, $j){$i or $j})",
                "tot": "jsonata"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 630,
        "y": 3240,
        "wires": [
            []
        ],
        "info": "# Only one or more properties of an object need to be true.\n\n Only one or more properties of an object need to be true.\n\n`{\n    \"Office\": false,\n    \"Bedroom\": false,\n    \"Living Room Balcony\": false,\n    \"Liviueng Room Right Window\": false,\n    \"Living Room Left Window\": false\n}`\n\nis false,\n\n`{\n    \"Office\": false,\n    \"Bedroom\": true,\n    \"Living Room Balcony\": false,\n    \"Living Room Right Window\": false,\n    \"Living Room Left Window\": false\n}`\n\nis true.\n\n# Mindestens eine Eigenschaft des Objektes muss wahr sein.\n\nMindestens eine Eigenschaft des Objektes muss wahr sein.\n\n`{\n    \"Büro Balkon\": false,\n    \"Schlafzimmer Balkon\": false,\n    \"Wohnzimmer Balkon\": false,\n    \"Wohnzimmer rechtes Fenster\": false,\n    \"Wohnzimmer linkes Fenster\": false\n}`\n\nergibt false,\n\n`{\n    \"Büro Balkon\": false,\n    \"Schlafzimmer Balkon\": true,\n    \"Wohnzimmer Balkon\": false,\n    \"Wohnzimmer rechtes Fenster\": false,\n    \"Wohnzimmer linkes Fenster\": false\n}`\n\nergibt true (wahr)."
    },
    {
        "id": "31176ff0.ed4e5",
        "type": "change",
        "z": "54b226bc.0793e8",
        "name": "NOT",
        "rules": [
            {
                "t": "set",
                "p": "payload",
                "pt": "msg",
                "to": "$not(payload)\t",
                "tot": "jsonata"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 790,
        "y": 3220,
        "wires": [
            []
        ]
    }
]

@hotNipi I already have several returns in some If() but I need several results and put them in more than one output at the end of my current function node.

@Colin Thanks for the hint with the short check for true/false.

@mickym2 That's one step beyond my general use of node-red and my Java-script knowledge. I have to investigate your code, how I have to use it and if it solves my needs. Thanks a lot.

Why not the node-red way with switch nodes ?

Thats one solution I consider. But to descide the way I wish to go I needed more information about alternate solutions. I learned Javascipt alog with my smart-home and node-red so my knowledge has some holes.

At moment I have a huge function node that check all sort of information and put them into a global node. Every var that itself is not a boolean has two objects, so global.get("var.v") ist the original value and global.get("var.b") is a boolean. If the content is a true (some cases if text is ther, and in some cases it the content is a good or bad condition). So at moment almost every value I use in nodered has true or false.

So I now have to check all conditions and do actions based on these but have to use the most easy to understand and modify way.

So it is no problem - you even do not need the obj variable.

In your 1st Post you said, you want to check some parameters - all I said is put in one object.

In your example:

if (msg.payload.on == true && global.get("Var") == true && ...) { }

you can assign all things to a property of you payload object. "on" is already a property. Next is the outcome of a global variable and so on.

So what you can do is:


msg.payload = {

	on: true,
	Var: global.get("Var")
	propertyNN : true

}

So additional parameters can be defined in the object.

With this code - you iterate through all properties of you payload object:

var x;
var bIsBoolean=true;
 
for (x in msg.payload) {
  bIsBoolean = bIsBoolean && msg.payload[x];
  
}

as bIsBoolean contains the result of each comparision you can use this further in your code or return this as result of your function node:

msg.payload=bIsBoolean;
return msg;

Means if any property of your payload object is false, the bIsBoolean is false and the overall result is false.

If you need a combination between ORs and ANDs you compare different objects and then combine them with an object with properties of the level below comparisions.

If you have no booleans by default in your property, you can use the conditional parameter and compare them with other properties of the message object.

See this flow:

Zusammenfassung
[{"id":"bcf8d2d4fabfa72f","type":"function","z":"a58e8f8b1f30dae3","name":"","func":"msg.payload = {\n\ton: true,\n\tVar: global.get(\"Var\"),\n    isCold : msg.temperature <= 5 ? true : false\n}\n\nvar x;\nvar bIsBoolean=true;\n \nfor (x in msg.payload) {\n  bIsBoolean = bIsBoolean && msg.payload[x];\n  \n}\n \nmsg.payload=bIsBoolean;\nreturn msg;\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":660,"y":220,"wires":[["a1d95df81b2f3ab2"]]},{"id":"91bb49312e864326","type":"inject","z":"a58e8f8b1f30dae3","name":"","props":[{"p":"temperature","v":"6","vt":"num"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":480,"y":220,"wires":[["bcf8d2d4fabfa72f"]]},{"id":"a1d95df81b2f3ab2","type":"debug","z":"a58e8f8b1f30dae3","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":830,"y":220,"wires":[]}]
1 Like

@mickym2 Thanks!
That's cool. isCold : msg.temperature <= 5 ? true : false was a new one.

At moment I have a central clock that request all current status of my devices and write them into global vars. I do many checks with the if ( ... && ... && ... && ... ) way, but I have three cases where I plan to do it now the way with your function example an save the data into global.get("subjec.b.title"") so I could reduce the code even more. Many thanks for this!

In my option to watch the current status - you should probably to think about the following solution.

For example I use an mqtt -in Node for all my shellies with the following topic:

shellies/+/online

all online topics are either true or false.

With a join node you can put the all into one object - which can directly analyzed with the code or a change node.

FYI, that "ternary" expression is more verbose than it needs to be -- it can be shortened to the more readable:
isCold: msg.temperature <= 5
since it already returns a true or false, depending upon the result of the comparison.

2 Likes

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