# Beginner questions on IF expressions and wildcard usage in function node

**URL:** <https://discourse.nodered.org/t/beginner-questions-on-if-expressions-and-wildcard-usage-in-function-node/80999>\
**Category:** General\
**Created:** [3 September 2023 11:43 UTC](https://discourse.nodered.org/t/beginner-questions-on-if-expressions-and-wildcard-usage-in-function-node/80999 "2023-09-03T11:43:38Z")\
**Posts on this page:** 20\
**Page:** 6

<div class="post-metadata">

**Author:** ![AleXSR700](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/alexsr700/32/41161_2.png) [@AleXSR700](https://discourse.nodered.org/u/AleXSR700)\
**Post date:** [6 September 2023 16:59 UTC](https://discourse.nodered.org/t/beginner-questions-on-if-expressions-and-wildcard-usage-in-function-node/80999/102 "2023-09-06T16:59:55Z")

</div>

What exactly is the `??` ? Kind of an if expression here? Because you are checking for 0 and then initializing. But that should never be true because the value is never 0.

I was trying

```auto
if (flow.get(msg.topic + '_Temperature') == undefined ) {
    flow.set(msg.topic + '_Temperature', msg.Temperature)
    return msg
}

```

when I noticed that the docs do not list the Else If case.

So is it  
`Else If { ...}` or `Else { If { }}`?

---

<div class="post-metadata">

**Author:** ![TotallyInformation](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/totallyinformation/32/31_2.png) [@TotallyInformation](https://discourse.nodered.org/u/TotallyInformation)\
**Post date:** [6 September 2023 17:01 UTC](https://discourse.nodered.org/t/beginner-questions-on-if-expressions-and-wildcard-usage-in-function-node/80999/103 "2023-09-06T17:01:18Z")

</div>

> [@AleXSR700](#):
>
> What exactly is the `??` ? Kind of an if expression here?

It is like `||` but safe for where you might be using a boolean value. It is true if the value is undefined or null but not if it is false.

---

<div class="post-metadata">

**Author:** ![AleXSR700](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/alexsr700/32/41161_2.png) [@AleXSR700](https://discourse.nodered.org/u/AleXSR700)\
**Post date:** [6 September 2023 17:05 UTC](https://discourse.nodered.org/t/beginner-questions-on-if-expressions-and-wildcard-usage-in-function-node/80999/104 "2023-09-06T17:05:21Z")

</div>

So, if undefined it will be set to whatever is behind the `??` ?

In that case I could replace my if expression with that like so?  
`if (Math.abs(msg.Temperature - flow.get(msg.topic + '_Temperature')) >= flow.get('XiaomiTemperatureDelta1') ?? msg.Temperature) {`

But still curious if I need if inside else or if Node-RED supports ElseIf. `Else If {` seems to work.

EDIT:  
No, I think I cannot replace my if. The `??`is probably just an alternative and does not initialize the context to that value, correct?

---

<div class="post-metadata">

**Author:** ![jbudd](https://avatars.discourse-cdn.com/v4/letter/j/5f8ce5/32.png) [@jbudd](https://discourse.nodered.org/u/jbudd)\
**Post date:** [6 September 2023 17:13 UTC](https://discourse.nodered.org/t/beginner-questions-on-if-expressions-and-wildcard-usage-in-function-node/80999/105 "2023-09-06T17:13:02Z")

</div>

> [@AleXSR700](#):
>
> What exactly is the `??` ?

If the expression `context.get("something")` evaluates to false  
(the context variable does not exist, _or it does exist but has the value false_)  
Then use the value 0.

![Untitled 1](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/e/2/e271af4061e3dc130707a25e4984c639f1b68263.jpeg)  
I think that using your function "Flow variables" to set values before using them elsewhere in the same flow is likely to be problematic.

---

<div class="post-metadata">

**Author:** ![TotallyInformation](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/totallyinformation/32/31_2.png) [@TotallyInformation](https://discourse.nodered.org/u/TotallyInformation)\
**Post date:** [6 September 2023 17:17 UTC](https://discourse.nodered.org/t/beginner-questions-on-if-expressions-and-wildcard-usage-in-function-node/80999/106 "2023-09-06T17:17:52Z")

</div>

> [@jbudd](#):
>
> If the expression `context.get("something")` evaluates to false  
> (the context variable does not exist, _or it does exist but has the value false_)  
> Then use the value 0.

Not quite, `||` includes false, `??` does not.

> **[Nullish coalescing operator (??) - JavaScript | MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing)**
>
> The nullish coalescing (??) operator is a logical
> operator that returns its right-hand side operand when its left-hand side operand is
> null or undefined, and otherwise returns its left-hand side
> operand.

> The **nullish coalescing (`??`)** operator is a logical operator that returns its right-hand side operand when its left-hand side operand is [`null`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/null) or [`undefined`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/undefined), and otherwise returns its left-hand side operand.

---

<div class="post-metadata">

**Author:** ![AleXSR700](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/alexsr700/32/41161_2.png) [@AleXSR700](https://discourse.nodered.org/u/AleXSR700)\
**Post date:** [6 September 2023 17:19 UTC](https://discourse.nodered.org/t/beginner-questions-on-if-expressions-and-wildcard-usage-in-function-node/80999/107 "2023-09-06T17:19:19Z")

</div>

> [@jbudd](#):
>
> I think that using your function "Flow variables" to set values before using them elsewhere in the same flow is likely to be problematic.

I think I mentioned it earlier that I disliked my initial idea of attaching it to the mqtt in because it constantly gets re-initialized.

I switched that to an inject node with "run once after 0.1 s". So they should always be available.

But on that topic, kind of, is there a way to delete **all** flow contexts in one go? The sidebar is quite tideous for this task 😃

---

<div class="post-metadata">

**Author:** ![Steve-Mcl](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/steve-mcl/32/4826_2.png) [@Steve-Mcl](https://discourse.nodered.org/u/Steve-Mcl)\
**Post date:** [6 September 2023 17:25 UTC](https://discourse.nodered.org/t/beginner-questions-on-if-expressions-and-wildcard-usage-in-function-node/80999/108 "2023-09-06T17:25:13Z")

</div>

> [@AleXSR700](#):
>
> delete **all** flow contexts in one go

There are 2 ways.

1. Store all your context in a single object - then just delete the 1 object.
2. Use a function node: [How to clear context? - #2 by Steve-Mcl](https://discourse.nodered.org/t/how-to-clear-context/80880/2)

---

<div class="post-metadata">

**Author:** ![AleXSR700](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/alexsr700/32/41161_2.png) [@AleXSR700](https://discourse.nodered.org/u/AleXSR700)\
**Post date:** [6 September 2023 18:32 UTC](https://discourse.nodered.org/t/beginner-questions-on-if-expressions-and-wildcard-usage-in-function-node/80999/109 "2023-09-06T18:32:29Z")

</div>

> [@Steve-Mcl](#):
>
> Use a function node: [How to clear context? - #2 by Steve-Mcl](https://discourse.nodered.org/t/how-to-clear-context/80880/2)

Perfect!!!

```auto
[{"id":"e64fea4887d59053","type":"function","z":"c36d205f4de85948","name":"Initialize flow variables","func":"// Thresholds tasmota ENERGY Power\nflow.set('Threshold1', 10)\nflow.set('Threshold2', 25)\nflow.set('Threshold3', 50)\nflow.set('Threshold4', 100)\nflow.set('Threshold5', 1000)\n\n// PowerDeltas tasmota ENERGY Power\nflow.set('PowerDelta1', 3)\nflow.set('PowerDelta2', 5)\nflow.set('PowerDelta3', 10)\nflow.set('PowerDelta4', 15)\nflow.set('PowerDelta5', 50)\n\n// TemperatureDeltas Xiaomi\nflow.set('XiaomiTemperatureDelta1', 0.3)\n\n// HumidityDeltas Xiaomi\nflow.set('XiaomiHumidityDelta1', 1.5)","outputs":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":730,"y":50,"wires":[]},{"id":"65b6414216f9efb6","type":"inject","z":"c36d205f4de85948","name":"Initialize flow variables","props":[{"p":"payload"}],"repeat":"","crontab":"","once":true,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":140,"y":50,"wires":[["e64fea4887d59053"]]},{"id":"d35b624de7c1676a","type":"function","z":"c36d205f4de85948","name":"Delete all flow variables","func":"const keys = flow.keys()\nfor (let index = 0; index < keys.length; index++) {\n const key = keys[index];\n flow.set(key, undefined)\n}\nreturn msg","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":450,"y":100,"wires":[["e64fea4887d59053"]]},{"id":"b4bf3edb1df92d53","type":"inject","z":"c36d205f4de85948","name":"Delete all flow variables","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":140,"y":100,"wires":[["d35b624de7c1676a"]]}]

```

---

<div class="post-metadata">

**Author:** ![AleXSR700](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/alexsr700/32/41161_2.png) [@AleXSR700](https://discourse.nodered.org/u/AleXSR700)\
**Post date:** [6 September 2023 18:46 UTC](https://discourse.nodered.org/t/beginner-questions-on-if-expressions-and-wildcard-usage-in-function-node/80999/110 "2023-09-06T18:46:37Z")

</div>

Two more questions:

- Is there a performance difference between context contexts and flow contexts?  
In theory my "previous" values do not need to be available to other paths in my flow. They could be limited to that one node were they are called and initialized.

- When I want to subtract two dates to create a time delta, I tried doing  
`msg.TimeDelta = (msg.Time.getTime() - msg.topic + '_Time'.getTime()) / 1000;`  
but that does not work because I am basically doing a maths operation while joining to strings to a new string.  
I tried this with brackets  
`msg.TimeDelta = (msg.Time.getTime() - (msg.topic + '_Time').getTime()) / 1000;`  
but that also does not work. So I figure that there is a trick do achiving this.

For context (not the variable, but the english word 😃 ):  
`flow.set(msg.topic + '_Time', msg.Time)`

---

<div class="post-metadata">

**Author:** ![TotallyInformation](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/totallyinformation/32/31_2.png) [@TotallyInformation](https://discourse.nodered.org/u/TotallyInformation)\
**Post date:** [6 September 2023 18:49 UTC](https://discourse.nodered.org/t/beginner-questions-on-if-expressions-and-wildcard-usage-in-function-node/80999/111 "2023-09-06T18:49:14Z")

</div>

> [@AleXSR700](#):
>
> Is there a performance difference between context contexts and flow contexts?

No. They are the same. The only difference is where you can access them.

> [@AleXSR700](#):
>
> When I want to subtract two dates to create a time delta, I tried doing

Don't forget that there is a vast world of knowledge out there! 😉

> **[javascript work out time difference - Bing](https://www.bing.com/search?q=javascript%2Bwork%2Bout%2Btime%2Bdifference)**
>
> Intelligent search from Bing makes it easier to quickly find what you’re looking for and rewards you.

---

<div class="post-metadata">

**Author:** ![AleXSR700](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/alexsr700/32/41161_2.png) [@AleXSR700](https://discourse.nodered.org/u/AleXSR700)\
**Post date:** [6 September 2023 18:51 UTC](https://discourse.nodered.org/t/beginner-questions-on-if-expressions-and-wildcard-usage-in-function-node/80999/112 "2023-09-06T18:51:46Z")

</div>

> [@TotallyInformation](#):
>
> Don't forget that there is a vast world of knowledge out there! 😉

Yeah, but the problem is not the how to do it but the naming due to my variable names being composed of different parts (see my flow.set I posted).  
`msg.Time.getTime() - msg.topic + '_Time'.getTime()`

I think node-red reads this as

msg.Time _ **minus** _ msg.Topic _ **plus** _ \_Time

It should read

msg.Time _ **minus** _ msg.Topic\_Time

where topic varies depending on the input data.

EDIT:  
And it seems `msg.Time.getTime()` is also not supported (`TypeError: msg.Time.getTime is not a function`). Apparently not a function. I would assume again because of the combination. So here it is probably the "." between msg and Time.

---

<div class="post-metadata">

**Author:** ![Steve-Mcl](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/steve-mcl/32/4826_2.png) [@Steve-Mcl](https://discourse.nodered.org/u/Steve-Mcl)\
**Post date:** [6 September 2023 19:09 UTC](https://discourse.nodered.org/t/beginner-questions-on-if-expressions-and-wildcard-usage-in-function-node/80999/113 "2023-09-06T19:09:51Z")

</div>

> [@AleXSR700](#):
>
> I think node-red reads this as
> 
> msg.Time _ **minus** _ msg.Topic _ **plus** _ \_Time
> 
> It should read
> 
> msg.Time _ **minus** _ msg.Topic\_Time

No, not Node-RED, **`JavaScript`** reads it exactly how you wrote it.

If you want to get a property using a variable name, use JavaScripts [square bracket notation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Property_accessors)

e.g.

```auto
const propName = msg.topic + '_Time'
const propVal = msg[propName]

```

> [@AleXSR700](#):
>
> And it seems `msg.Time.getTime()` is also not supported

That is likely because `msg.Time` is a string or number (i.e. not a `Date` object). Use the debug node to figure that out or call `node.warn(['typeof msg.Time', typeof msg.Time)` in your function

* * *
  

I know you keep saying you will post your code/flows when done, but I gotta be honest - you look like you are making a HUGE headache for yourself. Your means of encoding topic names, non camelCase variable names, (over) use of context, all function nodes etc etc etc - this is not gonna be fun to debug when you get bugs - and you will.

---

<div class="post-metadata">

**Author:** ![TotallyInformation](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/totallyinformation/32/31_2.png) [@TotallyInformation](https://discourse.nodered.org/u/TotallyInformation)\
**Post date:** [6 September 2023 19:17 UTC](https://discourse.nodered.org/t/beginner-questions-on-if-expressions-and-wildcard-usage-in-function-node/80999/114 "2023-09-06T19:17:54Z")

</div>

> [@AleXSR700](#):
>
> Yeah, but the problem is not the how to do it but the naming due to my variable names being composed of different parts (see my flow.set I posted).

No, I don't think it is. Perhaps this will help:

```auto
((new Date('2023-09-06 11:30:00')) - (new Date('2023-09-06 10:30:00')))/60000

```

Which returns 60 - the number of minutes between the 2 times - because JavaScript dates are in milliseconds offset from an origin. You only need getTime if you aren't interested in the dates. And if you used getTime and the two dates cross the midnight boundary, you'd likely get the wrong answer anyway.

Not sure what format your msg data is in sorry, I might have missed that bit. And not really sure what you are trying to do with the msg.topic. Don't mix strings and numbers unless you really have to as it can be hard to read and debug as you are discovering.

> [@AleXSR700](#):
>
> (`TypeError: msg.Time.getTime is not a function`)

getTime is a function of a JavaScript date object. You need a date, not a string.

---

<div class="post-metadata">

**Author:** ![AleXSR700](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/alexsr700/32/41161_2.png) [@AleXSR700](https://discourse.nodered.org/u/AleXSR700)\
**Post date:** [6 September 2023 19:38 UTC](https://discourse.nodered.org/t/beginner-questions-on-if-expressions-and-wildcard-usage-in-function-node/80999/115 "2023-09-06T19:38:54Z")

</div>

Here is an example:

```auto
{"topic":"tele/xiaomi/ATC801437","payload":{"mac":"a4c138801437","Temperature":25.6,"Humidity":73.3,"DewPoint":20.5,"Btn":0,"Battery":50,"RSSI":-95},"Time":"2023-09-06T21:40:52","_msgid":"48b050568f079c21","Temperature":25.6,"PowerDelta":0.40000000000000213,"TimeDelta":null,"CheckTime":"2023-09-06T21:40:52"}

```

So I would assume that msg.Time is a string.

Now I see that the `new Date()` is needed.  
So it should work with  
`msg.TimeDelta = ((new Date(msg.Time).getTime()) - (new Date(msg.topic + '_Time').getTime())) / 1000;`  
but I am getting `TimeDelta: NaN`

My idea was to format the strings and then get the time of those strings in one expression.

> [@Steve-Mcl](#):
>
> or call `node.warn(['typeof msg.Time', typeof msg.Time)` in your function

When I paste it into my function node I get a warning "expected one argument but got two" for the `typeof`.

> [@Steve-Mcl](#):
>
> I know you keep saying you will post your code/flows when done, but I gotta be honest - you look like you are making a HUGE headache for yourself. Your means of encoding topic names, non camelCase variable names, (over) use of context, all function nodes etc etc etc - this is not gonna be fun to debug when you get bugs - and you will.

Where did I miss using CamelCase? My contexts are all CamelCase.  
I am setting a few extra message properties right now for debugging purposes. They will be removed later. I am using them now to check the triggering condition and to see how long between two triggerings (in s) to check efficiency of my thresholds.  
I am using the topic names to be able to trace back the behavior to a device for debugging. Also not necessary but good for debugging right now.

I am a complete newbie, but right now I find my overuse quite useful for debugging because every step in processing is rather small and can only create a limited number of issues.

Right now the processing works perfectly. I am just struggling to get the bonus info of time delta working -.-

---

<div class="post-metadata">

**Author:** ![Steve-Mcl](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/steve-mcl/32/4826_2.png) [@Steve-Mcl](https://discourse.nodered.org/u/Steve-Mcl)\
**Post date:** [6 September 2023 19:46 UTC](https://discourse.nodered.org/t/beginner-questions-on-if-expressions-and-wildcard-usage-in-function-node/80999/116 "2023-09-06T19:46:24Z")

</div>

> [@AleXSR700](#):
>
> > [@Steve-Mcl](#):
> >
> > or call `node.warn(['typeof msg.Time', typeof msg.Time)` in your function
> 
> When I paste it into my function node I get a warning "expected one argument but got two" for the `typeof`.

I missed the closing square bracket

```auto
node.warn(['typeof msg.Time', typeof msg.Time])

```

---

<div class="post-metadata">

**Author:** ![Steve-Mcl](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/steve-mcl/32/4826_2.png) [@Steve-Mcl](https://discourse.nodered.org/u/Steve-Mcl)\
**Post date:** [6 September 2023 19:48 UTC](https://discourse.nodered.org/t/beginner-questions-on-if-expressions-and-wildcard-usage-in-function-node/80999/117 "2023-09-06T19:48:08Z")

</div>

> [@AleXSR700](#):
>
> Where did I miss using CamelCase? My contexts are all CamelCase.

`msg.Time` is not camelCase  
`msg.TimeDelta` is not camelCase  
`msg.Temperature` is not camelCase

> [@Steve-Mcl](#):
>
> PS: it is good practice to use [camelCase](https://www.w3schools.com/js/js_conventions.asp) in JS for your variable names (then you never forget if it starts with a capital letter etc)

---

<div class="post-metadata">

**Author:** ![AleXSR700](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/alexsr700/32/41161_2.png) [@AleXSR700](https://discourse.nodered.org/u/AleXSR700)\
**Post date:** [6 September 2023 19:53 UTC](https://discourse.nodered.org/t/beginner-questions-on-if-expressions-and-wildcard-usage-in-function-node/80999/118 "2023-09-06T19:53:36Z")

</div>

> [@Steve-Mcl](#):
>
> `msg.Time` is not camelCase  
> `msg.TimeDelta` is not camelCase  
> `msg.Temperature` is not camelCase

Those are not contexts. Those are msg properties. I presume you are talking about the "msg." part? Because "TimeDelta" and "PowerDelta" are CamelCase.

---

<div class="post-metadata">

**Author:** ![Steve-Mcl](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/steve-mcl/32/4826_2.png) [@Steve-Mcl](https://discourse.nodered.org/u/Steve-Mcl)\
**Post date:** [6 September 2023 19:56 UTC](https://discourse.nodered.org/t/beginner-questions-on-if-expressions-and-wildcard-usage-in-function-node/80999/119 "2023-09-06T19:56:26Z")

</div>

> [@AleXSR700](#):
>
> Because "TimeDelta" and "PowerDelta" are.

No, not. camelCase start with `lowerCaseLetters` and word joins are formed by a capital letter `likeThis` `andLikeThis`

Anyhow, it is a stylistic thing mainly, but using a common convention avoids issues with wondering - does it start with a captial or lower case? camelCase for JS is **always** lowercase first letter.

* * *

PS: "TimeDelta" and "PowerDelta" are `PascalCase`

---

<div class="post-metadata">

**Author:** ![Steve-Mcl](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/steve-mcl/32/4826_2.png) [@Steve-Mcl](https://discourse.nodered.org/u/Steve-Mcl)\
**Post date:** [6 September 2023 20:00 UTC](https://discourse.nodered.org/t/beginner-questions-on-if-expressions-and-wildcard-usage-in-function-node/80999/120 "2023-09-06T20:00:05Z")

</div>

> [@AleXSR700](#):
>
> > [@Steve-Mcl](#):
> >
> > `msg.Time` is not camelCase  
> > `msg.TimeDelta` is not camelCase  
> > `msg.Temperature` is not camelCase
> 
> Those are not contexts.

No one said they were.

camelCase applies to property names and function names. in `msg.xxx`, msg is the object, xxx is the property. so `Xxx` is not camelCase.

---

<div class="post-metadata">

**Author:** ![AleXSR700](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/alexsr700/32/41161_2.png) [@AleXSR700](https://discourse.nodered.org/u/AleXSR700)\
**Post date:** [6 September 2023 20:00 UTC](https://discourse.nodered.org/t/beginner-questions-on-if-expressions-and-wildcard-usage-in-function-node/80999/121 "2023-09-06T20:00:08Z")

</div>

Ah well, that is not the definition of CamelCase. The definition of CamelCase does not specify the first letter. It only specifies that words are joing by using uppercase for the next word.

But if that is the convention or the generally used approach for JS, then that is fine of course.

I like using uppercase for the first letter because almost all systems use lowercase for the first letter by default. So as soon as a string starts with uppercase, you know it is my string.

msg.payload is system generated. msg.time is system generated. msg.Time is user generated. msg.Payload would be user generated.

We are splitting hairs here and I mean no offense but

The more specific terms **Pascal case** and **upper camel case** refer to a joined phrase where the first letter of each word is capitalized, including the initial letter of the first word. Similarly, **lower camel case** (also known as **[dromedary](https://en.wikipedia.org/wiki/Dromedary) case** ) requires an initial lowercase letter.

So I am using CamelCase, but not _ **lower** _ CamelCase 😉

[Previous page](https://discourse.nodered.org/t/beginner-questions-on-if-expressions-and-wildcard-usage-in-function-node/80999.md?page=5)

[Next page](https://discourse.nodered.org/t/beginner-questions-on-if-expressions-and-wildcard-usage-in-function-node/80999.md?page=7)
