Why doesn't RED.nodes.createNode apply the config to this itself?

I guess this may be one for @knolleary when he is back from his hols but ...

When you do RED.nodes.createNode(this, config) for you node instance, why doesn't createNode apply config to this for you?

It seems a long-winded step to have to go and individually apply the config properties to this yourself.


I am looking at the best ways to decompose the node runtime definiton and I think I've come a long way now. With some simple tricks it is possible to get a much clearer and more robust structure. I will post my progress to another thread shortly though some of the thinking is here:

Because it didn't occur to us (me) to do something like that until it was too late to consider without potentially breaking nodes that didn't expect that behaviour.

OK, thanks for that. It isn't a big deal - however, maybe something that could be improved (in a backwards compatible way of course) in a future release?

I'm also finding it facinating how that function treats this in a way that hadn't occured to me could happen.

Basically, when using a function outside of the export. If you try to access this before the call to createNode, you can not. But if you try afterwards, you can! Very strange - though I'm sure there will be an answer I'm too thick to have comprehended :grinning:

Just writing up a minimal example node definition using what I've discovered so far about destructuring the code.

That was my point... there is no way to introduce it in a backward compatible way.

If the config properties were added to this in createNode, I think that would be compatible?

For all existing nodes that use the this = that and then add the config properties manually, that would still work just fine I think.

But new nodes could miss off that step if they wanted to.

There are some overlapping property names but they all seem to have the same content anyway so I don't think that matters either?

But you cannot guarantee it. A node may have some logic around setting this.foo based on the value of config.foo and other properties. If we unilaterally set it, it would break. I remember finding a concrete examples of this when I looked at it a few years ago.

The node object, with all of its internal workings, hasn't been created until you call createNode. That is why it's the first thing the node constructor function needs to do.

Thanks for the explanation Nick, that makes sense.

It is just weird that you HAVE to pass this (I tried it with something else :grinning: ) even though you cannot actually reference this in your code until after the call.

I'm sure there is a logical reason for it, it just doesn't look logical. However, it works and I'm using it. So not worth disturbing anyone about.

Forcing me to learn more about the inner workings of Node-RED! :sunglasses:

Currently, I use createNode as:

class MyCustomNode {
  constructor(config) {
    createNode(this, config);
  }
}

It would be awesome if it could be:

class MyCustomNode extends CreateNode {
  constructor(config) {
    super(config);
  }
}

EDIT: I just ran a quick and dirty test to see what createNode does. It seems that the main thing it does is to attach any credentials to the Node object.

I was able to extend the Node class to create a functional node-red node without the need to call createNode like this:

const Node = require('/usr/lib/node_modules/node-red/node_modules/@node-red/runtime/lib/nodes/Node.js');

class Mp4fragNode extends Node {
    constructor(config) {
      super(config);
  }
}

It simply worked (probably because my node does not use credentials). If the credential grabbing logic was moved from createNode to the Node class constructor, then createNode seems like it could remain backwards compatible, while also allowing the Node class to be exportable to be used as shown above with the extends class syntax.

There have been some nodes implemented using 'true' JavaScript classes.

You're right they are largely compatible and possibly a clearer way to structure things. If we were to change our recommended approach, I suspect this would be more akin to what we'd do.

2 Likes

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