I developed a long time ago the node-red-contrib-msg-speed node. But I need to develop another node, which needs the reuse most of the internals as the speed node. I would like to share the functionality between both nodes, to avoid having to maintain it twice...
What is the best way to deal which such a situation:
Extract that functionality from the speed node and isolate it into a new separate npm package (and let both nodes use that package as a dependency).
And do you have any good practices for such a common NPM package?
My simplified speed-node package contains this:
module.exports = function(RED) {
"use strict";
var CircularBuffer = require("circular-buffer");
var Math = require("mathjs");
function speed(config) {
RED.nodes.createNode(this, config);
// Initialization code
this.on("input", function(msg) {
// Message handling code
});
this.on("close",function() {
// Cleanup code
});
}
RED.nodes.registerType("msg-speed", speed);
};
Do you have any advise on how such a common NPM package could look like (and how I can call it both my nodes)?
Because most of the code in the 3 code blocks would be common for both nodes, but each node also needs to execute some dedicated code in each block ...
In fact I mean that every of the 3 blocks (initialization, message handling, cleanup) contain shared code, which should be part of the common npm package. But my both nodes - which depend on this package - should be able to execute their own code in each block.
Probably there is a very simple solution, but I don't see it at the moment ...
Well if they are related functions (ie also to do with speed) - such that you would ship them both as one package then you can define them both in the same files. If not then not easily no.
For anybody who needs to do something similar in the future, below you can find how I did it. Although there might be many ways to get to Rome ... But since I have a background as object oriented developer, I really wanted to use ES6 classes to accomplish this. So no callback functions for me this time
In the new Github repository, I encapsulated all the shared functionality into a class (which will be exported):
module.exports = class MessageAnalyzer {
constructor (config) {
// Do some initialization, and store the Node-RED node config into this instance
this.someProperty = config.someProperty;
...
}
someMethod(someParameter) {
...
this.doSomething();
...
this.doSomethingElse();
...
};
doSomething() {
}
doSomethingElse() {
}
}
The someMethod contains my old logic (of the speed node), which I want to reuse in other nodes.
But at some points in the code I call the (e.g. empty) methods doSomething and doSomethingElse.
I added the new npm package as a dependency in the package.json file of my speed node:
The speed node now imports this class, and creates a subclass of it. That subclass will override the methods doSomething and doSomethingElse to do stuff that is specific to this speed node:
module.exports = function(RED) {
function speedNode(config) {
RED.nodes.createNode(this, config);
var node = this;
const MessageAnalyzer = require('nr-msg-statistics');
class MessageSpeedAnalyzer extends MessageAnalyzer {
doSomething() {
// Do some speed related stuff
}
doSomethingElse() {
// Do some other speed related stuff
}
}
// Create an intance of the subclass
var messageSpeedAnalyzer = new MessageSpeedAnalyzer(config);
// By calling this method, underneath the doSomething and doSomethingElse will be called.
messageSpeedAnalyzer.someMethod(...);
}
}
So I can reuse the code (in the MessageAnalyzer class) to share it between multiple Node-RED nodes, and each node can overwrite the methods to do stuff that is specific to that node ...
Damn it was fun working with classes after a long time