Sending a message upon startup in a custom node

I need my node to automatically send a message upon its initialization.
In a function node, I can just create & send a message in the function node's On Start tab:
image

However, when I try to apply the same practice in a custom node, the message is not sent.

module.exports = function(RED)
{
    function xxxNode(config)
	{
		RED.nodes.createNode(this,config);
		const node = this;
		
		node.send({payload:config.initVal});  // **** This doesn't work!!  ****

		node.on('input', function(msg, send, done)
		{
			// ...Do something...
			send(msg);  // This works
			done();
		});
	}
    RED.nodes.registerType("XXX",xxxNode);
}

I know I can use another node to send a startup message into my custom node, but want to keep this logic hidden & self-contained.

Am I doing something wrong?

BTW, other node methods such as node.warn(), node.error() etc. also do not work outside of "on input".

I've never made a node. Only subflows.

Although others may get it, I won't get what I am about to ask:

Can you show me a bigger picture of how this all fits in to your new node?

If it is a function node can you show me where this node is in your layout?

Never tried to send a msg that early. Maybe try wrapping the send in a setTimeout and play with the delay to see if that works.

There is a utility function that will output a msg to the debug panel but I don't know if that can be made to output a generic msg.

As @TotallyInformation mentions, you have to use some type of delayed action. If you look through the source code of the inject node, you will see how it is done.

Could also HOW you are deploying the node change what you get?

Does this help?

[{"id":"6411c4f3ce7cb3db","type":"function","z":"d188b95f33e5f7e4","name":"function 32","func":"\nreturn msg;","outputs":1,"noerr":0,"initialize":"// Code added here will be run once\n// whenever the node is started.\nnode.send({\"payload\":\"This is a test message\"});\n\nreturn msg;","finalize":"","libs":[],"x":360,"y":90,"wires":[["fac2bc76b93fb932"]]}]

Thanks.
Are you referring to node.warn(), node.error() etc.? They also don't work outside of the "on input" handler (not even in "on close").

Thanks.
This works, but as I mentioned in my original post, I want to implement this in a custom node, not a function node.

Have you checked that config.initVal is defined in the contexts you are using? You could try

node.send({payload:"hello world"})

The suggestions about timing assume that the message is actually sent but not received. How are you expecting to see the message, warning, or error? Downstream nodes may not be deployed yet, but I would expect the sidebar or console to be ready for input.

const msg2 = RED.util.encodeObject(
    { id: this.id, z: this.z, _alias: this._alias,  
      path: this._flow.path, name: this.name, 
      topic: msg.topic, 
      msg: { payload: 'hello' } 
    },
    { maxLength: 1000 }
  )

RED.comms.publish('debug', msg2)
1 Like

My example was only to show you how to do it from a function node.

As I said: I have never made a node.

But I'm guessing that somewhere in the scheme of things, actual nodes are used.
(or not) :man_shrugging:

But you could use the mechanics used in this example to do what you need - maybe.

1 Like

Thanks.
Yes, I have also tried with "Hello" messages, and as you correctly mentioned, it seems that the message is being sent, but not received by the target nodes.
I also assumed it's a timing issue (downstream nodes still not finished initializing), but then (as you correctly mentioned again) node warn & error messages should have been able to reach the debug pane.
Maybe @knolleary could solve the mystery.

If you log to the console (server side) then you should see the message - but the sidebar in the browser has to retry and to reconnect the web socket before it can receive any messages - so anything sent really early on is unlikely to make it to the sidebar.

Thanks.
Indeed, the message shows on the console. So if you say that when the node instance is starting it is still not connected to the messaging framework, it means that we probably don't have an "on start" section in custom nodes (like we have in function nodes).

There are absolutely sections of code in a custom node that execute at different times, including code that runs on load and on start. All this is saying is that the "messaging" framework isn't ready when that code runs. A slight delay added - possibly along with a flag to make sure it only runs once - should do the job. I think there are also hooks you might be able to use as well, I don't currently use any of the hooks so I don't remember off the top of my head.

Personally, I've restructured my runtime code in a way that I think is more logical and clear so that I don't get myself confused about what is run when. Check out any of the uibuilder nodes for examples.

Thanks for your response.
Are you able in your nodes to "know" that the node is ready, or just experiment with a delay?
I have seen the same issue with dashboard widgets. I need to wait ~100 ms until the dashboard scoket connects, before they accept data.

The runtime emits an event when the flows are started:

When you listen to this event & act accordingly, you'll be on the save side...

1 Like

Thanks!
I'll try it

To be honest, I've never had to worry about it too much. I've several async functions in the main uibuilder node's libraries but they all seem to be ready in time for them to be used.

That will be about the fact that Dashboard has to send quite a bit of data to the browser and then it all needs initialising and running before anything else can happen. It's a bit of a monster. But hey, it works. :slight_smile:

Yes, I forgot about that. Though I do, in fact use it. This is in the runtimeSetup function in uibuilder's runtime:

However, it happens well before the flows are started and therefore well before messages can be "sent" between nodes:

Looks like your launch message is created on('runtime-event', ...) ... which is another event, yet not the one I was referring to.