Trigger node does NOT support JSONata on ouptput messages

Hi All,

A very happy user of Node-RED here. Thank you all for the hard work.

I have noticed that the Trigger node is missing JSONata (J: Expression) option to compose output messages. I ran in to an issue where the output message(s) depended on some values from the incoming msg.payload.

I understand that there could be workarounds to achieve what I'm looking for. But I'm wondering if this was an intentional design decision

Regards,

Hi, indeed - at the time of creation JSONate was probably not anywhere apart from the change node. As you suggest it's not hard to add a change node to follow to achieve the same. It could certainly be added if anyone felt strongly enough to offer up a Pull Request, or we can add it to the backlog.

@dceejay,

Thank you for the quick response. I have never delved deep in to the source of Node-RED, but if you could kindly give some pointers about where and what to look for; I'd be happy to give it a shot.

In the meantime, for anyone who is looking for a quick way out of a similar situation, I got it done using a function node with the following code:

var first_msg = { payload: msg.payload + "_first" };
node.send(first_msg);

var delayed_msg = { payload:msg.payload + "_delayed" };
setTimeout(function() {
    node.send(delayed_msg);
}, 500);

Whoever came up with the idea of the function node, God bless him/her!

You could have done it with the standard Trigger node telling it to send the two messages to different outputs, with a Change node on each, adding the extra text. However, if your function node does what you want then that is ok, obviously.

@Colin ,

You are absolutely right.

Even better, a Trigger node with J: expression capability would have sufficed by itself. I don't know if I have some un-diagnosed OCD or what but using more nodes than needed irks me to no end. Which is why I made the suggestion in the op, and also ended up using a single function node.

Cheers,

Certainly.
I tend to avoid Function nodes unless they save a significant number of core nodes. There is a small overhead in function nodes compared to 'real' nodes, but more significantly any time one is writing code there is a much greater chance of unnoticed bugs creeping in. For example, have you considered what will happen if you get another message arriving at the function before the second original message has been sent?

@colin - yes there is a small overhead - but there is also an overhead when calling JSONata, so unless you are doing 100's of messages a seconds - don't sweat it.

But yes - good point re subsequent messages - as the JSONata needs to be evaluated should that be done immediately on the original message values - or at the point of sending the second message at which point the values in the last arriving message may be used. I tend to think it should probably be the latest/most current values that get used.

I was specifically meaning with the function suggested, which will have unexpected results in that situation I think.
However that is a good point wrt adding J: to the output options as it brings in a completely new concept to the node. Currently, for the second message one can only output a pre configured message, the first message, or the latest. With J: one has the additional option of using a modified version of the input message. For full flexibility I think one would need the option of applying this to either the first or the latest. As is so often the case an apparently simple enhancement gets more complex as one looks at it in detail.

I think if implemented it would be on latest value only. As JSONata has hooks into so many other things like context and time then I would expect all those things to have possibly changed at the instant of sending.. eg if I wanted to append a timestamp or add a constant factor from context etc.

Alternatively this is one of those cases where two nodes are better than one :slight_smile:

@Colin, Good catch!

I did not think about the scenario where a preemptive message arrives. This should fix it. Now, the function returns immediately with the content of the second message getting composed and passed as a parameter to setTimeout as quickly as possible. Still not bullet proof, but should take care of 99% of the cases where microsecond-level resolution is not needed.

var first_msg = { payload: msg.payload + "_first" };
var delayed_msg = { payload:msg.payload + "_delayed" };

node.send(first_msg);
setTimeout(node.send, 500, delayed_msg);

But, I do agree that there is a risk of such kind of subtle details remaining buried inside of function nodes.

I don't see how this differs in operation to the first version. node.send() returns immediately and will start the timeout. The problem (if it is a problem) is that if you send in two messages close together then the output will be the _first response for the first message, followed by the _first for the second message, followed by _delayed for the first and _delayed for the second.
This all goes to show the reason that such functions are best avoided if possible, there are many traps for the uninitiated (and the initiated) to fall into. Much better where reasonable to use core nodes that have been tested extensively and should give the expected results.

Well, logically that is what is supposed to happen; as long as the delayed message of the of the first message is not overwritten by the preempting one. The fix I was referring to was to protect the content of the _delayed response of the initial message not to be overwritten by second.

That depends on what the application is. That is not what the Trigger node does.

That won't happen, each message will get its own set of local variables (first_msg and delayed_msg). That is why you have to use node context if you want data to be passed between different invocations of the function node.

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