Why don't Node-RED nodes allow multiple inputs?

For clarity:
I'm not asking how to implement multiple inputs to a function, I already know the workarounds. I want to know why Node-RED developers would inhibit such a functionality.

It seems so obvious and natural to allow multiple inputs to a function.

For example: say I want to create a function Divide(dividend, divisor) that returns dividend divided by divisor. In JavaScript this would be:

function Divide(dividend, divisor) {
  return dividend / divisor

With Node-RED, the same function looks like this:

var dividend = 0
var divisor = 0

if (msg.topic == 'dividend')
    dividend = msg.payload
    context.set('dividend', dividend)
    divisor = context.get('divisor')
else if (msg.topic == 'divisor')
    divisor = msg.payload
    context.set('divisor', divisor)
    dividend = context.get('dividend')

return {payload:(dividend/divisor)};

(In addition, I have to assign topics 'divisor' and 'dividend' to the inputs so that the function doesn't get confused between which is which)

I understand that this is because Node-RED is message-based rather than functional, but I can't really be the only person who thinks this is an absurd amount of effort for such a simple task, right?

I understand that I could avoid using context if I used a join node and wait to receive two messages, but I want my function to update upon any change of input, since otherwise the function's output would be out-of-date until the second message is received.

I would imagine if developers implemented a multiple input functionality, the function would run upon receiving a new message on any of its inputs, and since messages on any given wire are retained by default until the next message is sent, you wouldn't have to worry about implementing retention using context.

Also, if you were able to name function inputs, you wouldn't have to worry about sorting the inputs by topic and explicitly assigning a topic to each of your inputs to support this.

Is this a deficiency of Node-RED or am I completely missing the point?

1 Like

Think about this - how would you synchronise the triggering of inputs? So let's say you use 2 change nodes to set parameter X & Y then triggered by same item, this would be no different from setting msg.X and msg.Y then sending 1 message to the function. However, the singular input guarantees both function parameters are sent together.

I'm not saying their isn't a place for multiple inputs I just think it may introduce more problems than solves - or - indeed may solve a different problem (like multiple functions)

But you still need them both in order to complete the function, so join is the better choice.

As non-developer, you've got a point that combining two messages takes a fair bit of work

But I think its just one of the downsides of the Node-RED programming paradigm (all languages have them)

However, the upsides of the Node-RED flow-based processing, make it easy to do stuff that would be a lot of work in other languages.

I'm using Node-RED across 6 computers with hundreds of flows and only in a few of them do I have to deal with processing 2 inputs in one function node so I think its a small problem

My solution is to set flow variables so that I don't need code inside a function to handle the issue

[{"id":"dc810972.eae048","type":"inject","z":"6f615236.c9bffc","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":180,"y":80,"wires":[["713189b4.385b28"]]},{"id":"1fa86359.711b4d","type":"inject","z":"6f615236.c9bffc","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":180,"y":160,"wires":[["e4b18db.44e5e7"]]},{"id":"713189b4.385b28","type":"change","z":"6f615236.c9bffc","name":"","rules":[{"t":"set","p":"dividend","pt":"flow","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":360,"y":80,"wires":[["c4f32506.acdf68"]]},{"id":"e4b18db.44e5e7","type":"change","z":"6f615236.c9bffc","name":"","rules":[{"t":"set","p":"divisor","pt":"flow","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":360,"y":160,"wires":[["c4f32506.acdf68"]]},{"id":"c4f32506.acdf68","type":"function","z":"6f615236.c9bffc","name":"","func":"\nreturn {payload:(flow.get('dividend')/flow.get('divisor'))};","outputs":1,"noerr":0,"x":570,"y":120,"wires":[["e5a1aa80.bc9678"]]},{"id":"e5a1aa80.bc9678","type":"debug","z":"6f615236.c9bffc","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":790,"y":120,"wires":[]}]



Say that I receive messages from multiple different sensors only when their respective inputs change by 1 LSB.

I want to update the result every time an input is updated, so that I always have the correct result. Also, since there is no order to the messages, waiting for two messages to be received would result in unpredictable and slow behaviour. For example, if sensor A is updating its output on average 5 times a second, and sensor B is updating its output on average once every minute, using a join would mean my calculation would only update once a minute instead of 5 times a second.

1 Like

Hi cymplecy,
I like your implementation, however it means that every time I use a new Divide function node within the same flow, I will need to create new flow variables each time.

I think if I'm just using the function node once, then I will do it your way. If I need to reuse it multiple times in the same flow, I'd probably stick with doing it my way.


1 Like

Thanks for your reply Steve,

Please see my reply to bakman2

You can configure the Join node to join messages from separate topics into a single Object and send that updated object whenever another message arrives. So this scenario you highlight is already handled.

1 Like

You don't have to. The flow variable is used for the flow, so you don't even have to connect it, just update when a new value arrives.

Thanks knolleary,

Right I just figured it out.

I didn't notice the "and every subsequent message" tickbox in the join node.
Now it's a lot simpler.


Thanks a lot!