I have some issues understanding NODEJS syntaxing. Im used to working with php code.
So im trying to do something I did prior in node js but failing
'''
inside a class Machine I use this code
interpolate_lin_curve_points(i_curve, o_min, o_max){
//declare internal vars
let o_curve = []; // output is an array
let i_min = 0;
let i_max = 0;
//define min and max of curve
i_min = Math.min(i_curve);
i_max = Math.max(i_curve);
//Loop over results and write code in curve
i_curve.forEach(fillcurve);
//define function to fill output curve
function fillcurve(value, index){
o_curve[index] = this.interpolate_lin_single_point(value, i_min, i_max, o_min, o_max);
}
return o_curve;
}
'''
The above code gives me the following error :
TypeError: Cannot read properties of undefined (reading 'interpolate_lin_single_point')
When I use this directly within another defined function like this :
'''
limit_input(input,min,max){
//declare internal vals
let output;
//limit function below or above min or max
if ( input < min){
output = min;
this.warning = "Minimum limit reached";
}
else if ( input > max){
output = max;
this.warning = "Maximum limit reached";
}
else{
output = input;
}
return output;
}
//Interpolate 1 single point
interpolate_lin_single_point (i_number, i_min, i_max, o_min, o_max){
//declare internal vars
let o_number;
//if min isnt equal to max interpolate else the output is equal to the input
if ( i_min != i_max){
o_number = o_min + ( i_number - i_min ) * ( o_max - o_min ) / ( i_max - i_min );
}
else{
o_number = i_number;
}
//cap min and max to output min and max
o_number = this.limit_input(o_number,o_min,o_max);
return o_number;
}
'''
it works perfectly fine...
Im just trying to loop over some array and allready having headaches.
Cheers for whoever can point me in the right direction !
If your array is in msg.payload then the "low-code" approach is to pass it through a split node, then you get each element as a single object you can work on. If needed, you can re-combine the data back into an array using the join node.
How is this different than what i wrote in the class function?
I dont want a low code approach since im writing my own node.
Ill simplify it some more :
I have a class in my node code
Class Machine {
// in my class i have some functions defined in the class
somefunction1(){
//doing stuff
}
//i have a second function which uses somefunction1
somefunction2(){
//doing stuff with function 1
test = this.somefunction1();
}
// Above works fine when called outside of the function
//Below is the problem
somefunction3(){
//uses a function within this function because apparantly I cant use a foreach loop in another manner within nodejs
//Loop over results using a function
somearray.forEach(someinternalfunction);
//declare someinternal function
function someinternalfunction(){
//telling the function what to do using another class function
test = this.somefunction1();
}
}
}
That wasn't clear (and your post is in the wrong section (I'll move it)
Can you post the class code & where you call it from - your post is a bit unclear. If I were to guess then you have a this issue or are trying to call the function on an uninstantiated instance or similar.
Also please always wrap code in backticks to improve readability and prevent the forum renderer messing up the code.
``` paste code with 3 backticks above and below (like this) ```
class Machine {
//construct default pump data
constructor() {
//general vars
this.type = ""; // Type of machine to pass on to child classes
this.id = ""; // Unique machine number starting from 1
this.state = 1; // State = 0 the machine is turned off , state = 1 the machine is turn
//stored variables
this.prev_state = 1; // Stored previous output state of machine
this.prev_internal_state = 1;
this.internal_state = 1;
//used in calculation
this.best_powerresult_ctrl = 0 ; // Use this to store best power output before deciding what the actual
this.best_powerresult_flow = 0 ; // Use this to store best power output before deciding what the actual
this.best_powerresult_power = 0 ; // Use this to store best power output before deciding what the actual
this.best_flowresult_ctrl = 0 ; // Use this to store best flow output before deciding what the actual
this.best_flowresult_flow = 0 ; // Use this to store best flow output before deciding what the actual
this.best_flowresult_power = 0 ; // Use this to store best flow output before deciding what the actual
//output values
this.o_ctrl = -1 ; // Stored output ctrl of machine
this.o_flow = 0 ; // Stored output flow of machine
this.o_power = 0 ; // Stored output power of machine
this.o_error_code = 0 ; // Stored output error code
this.o_error_text = "" ; // Stored output error code
this.warning = "" ; // return warnings to user
//specifics of this machine
this.name = "undefined" ; // Name of machine
this.time_on = 0 ; // Total time this was turned on in seconds
this.time_off = 0 ; // Total time this was turned off in seconds+
this.cooldown = 5 ; // When the machine turns off it needs to cool down. Enter the
this.warmup = 10 ; // When the machines turns on it needs to warm up before it do
this.cooldown_timer = 0 ; // Keep track of the cooldown until it hits zero
this.warmup_timer = 0 ; // Keep track of the warmup until it hits zero
this.sync_delay = 0.01 ; // Store sync delay expressed in seconds per % from min to max
this.startup = 10 ; // when the machine turns on it requires some time to push its
this.startup_timer = 0 ; // Keep track of the startup until it hits zero.
//normalize curve between min and max ctrl
this.min_normalize = 0 ; // by default 0
this.max_normalize = 1000 ; // The higher this is the more accurate the result ca
this.open_curve_number = 0 ; // this value is set in the construction fase of the
this.open_curve_divider = 1.35 ; // division of opening curve the higher this number t
this.init = false ; // When this function is constructed this will be
this.max_precision ; // define max precision per individual machine
}
//////////////////////////////////Getter / Setters /////////////////////////////////////
//set cooldown timer
set cooldown_timer(value){
this._cooldown_timer = value;
}
//get cooldown timer (we use _ to not create a getter loop)
get cooldown_timer(){
return this._cooldown_timer;
}
//set new cooldown value
set cooldown(value){
this._cooldown = value;
}
//get cooldown default value
get cooldown(){
return this._cooldown;
}
//set new sync delay value
set sync_delay(value){
this._sync_delay = value;
}
//get sync delay default value in % / seconds
get sync_delay(){
return this._sync_delay;
}
//set new machine number value
set number(value){
this._number = value;
}
//get machine number
get number(){
return this._number;
}
//set new machine number value
set type(value){
this._type = value;
}
//get sync delay default value in % / seconds
get type(){
return this._type;
}
//set new machine number value
set state(value){
this._state = value;
}
//fetch current state
get state(){
return this._state;
}
//set new machine name value
set name(value){
this._name = value;
}
//fetch current state
get name(){
return this._name;
}
//set resolution value
set min_normalize(value){
this._min_normalize = value;
}
//fetch resolution
get min_normalize(){
return this._min_normalize;
}
//set resolution value
set max_normalize(value){
this._max_normalize = value;
}
//fetch current state
get max_normalize(){
return this._max_normalize;
}
//set warning value
set warning(value){
this._warning = value;
}
//fetch current state
get warning(){
return this._warning;
}
////////////////////////////////////FUNCTIONS/////////////////////////////
//turn machine on
switch_on(){
//change state
this.state = 1;
// and control to min?
}
//turn the machine off
switch_off(){
//turn state to zero
this.state = 0;
//turn control to zero ?
}
//hand control from scada overwrites automatic control algo cant use this machine
force_on(){
this.state = 3
}
//hand control from scada overwrites auto control algo cant use this machine
force_off(){
this.state = 4;
}
//Limit numbers between min and max
limit_input(input,min,max){
//declare internal vals
let output;
//limit function below or above min or max
if ( input < min){
output = min;
this.warning = "Minimum limit reached";
}
else if ( input > max){
output = max;
this.warning = "Maximum limit reached";
}
else{
output = input;
}
return output;
}
//Interpolate 1 single point
interpolate_lin_single_point (i_number, i_min, i_max, o_min, o_max){
//declare internal vars
let o_number;
//if min isnt equal to max interpolate else the output is equal to the input
if ( i_min != i_max){
o_number = o_min + ( i_number - i_min ) * ( o_max - o_min ) / ( i_max - i_min );
}
else{
o_number = i_number;
}
//cap min and max to output min and max
o_number = this.limit_input(o_number,o_min,o_max);
return o_number;
}
//make a new curve and convert it between defined min and max
//we use this to normalize the pressure curve so that all comparisons with points are done on the same starting and end pressures
interpolate_lin_curve_points(i_curve, o_min, o_max){
//declare internal vars
let o_curve = []; // output is an array
let i_min = 0;
let i_max = 0;
//define min and max of curve
i_min = Math.min(i_curve);
i_max = Math.max(i_curve);
//Loop over results and write code in curve
i_curve.forEach(fillcurve);
//define function to fill output curve
function fillcurve(value, index){
o_curve[index] = this.interpolate_lin_single_point(value, i_min, i_max, o_min, o_max);
}
return o_curve;
}
}
//what to do on input
node.on('input', function(msg) {
//make new machine
var machine = new Machine();
var msg1 = {payload : 0,topic:""};
/*example
//Set the cooldown timer to the machine default cooldown time
machine.cooldown_timer = machine.cooldown; //start cooldown timer at default value
//return the cooldown timer variable
msg.payload = machine.cooldown_timer; // Will output 'Hello, my name is Martin, I have ID: id_1'
msg.topic = "cooldown_timeleft";
*/
//example usage lin interpolation functions
//msg1.payload = machine.interpolate_lin_single_point(msg.payload, 0, 10, 0, 100);
let test = [0,234,433,693];
//example usage curve interpolation
msg1.payload = machine.interpolate_lin_curve_points(test, 0, 10000);
//return state of machine
msg.topic = "Machine state";
msg.payload = machine.state;
node.send([msg,msg1]);
// If an error is hit, report it to the runtime
});
}
RED.nodes.registerType("pump",pump);
}
Msg1.payload is giving me the error. Im calling the function from within a class function.
Since interpolate_lin_single_point is a pure function, make it static then you can call it anywhere, without making a new instance, but instead, by calling it from the ClassName.Function() e.g. Machine.interpolate_lin_single_point()
So how would you solve this? Ive been looking at static methods but i want to do it from within the class. As shown in my code.. i mean in php its so simple why is this so hard in java?
Yeah thats not what I wanted I sorted it in another way..
So all the code remains the same apart from this bit :
interpolate_lin_curve_points(i_curve, o_min, o_max){
//declare internal vars
let o_curve = []; // output is an array
let i_min = 0;
let i_max = 0;
//define min and max of curve
i_min = Math.min(...i_curve);
i_max = Math.max(...i_curve);
//Loop over results and write code in curve
i_curve.forEach((val,index) => {
o_curve[index] = this.interpolate_lin_single_point(val, i_min, i_max, o_min, o_max)
});
return o_curve;
}
the looping over results uses a => apparantly to fix the this problem and gives me the same as the php did before like this :
//convert a curve to o min and o max points
public function interpolate_lin_curve_points($i_curve, $o_min, $o_max){
//define min and max of curve
$i_min = min($i_curve);
$i_max = max($i_curve);
//Loop over results and write code in curve
foreach($i_curve as $i_number)
{
$o_curve[] = $this->interpolate_lin_single_point($i_number, $i_min, $i_max, $o_min, $o_max);
}
return $o_curve;
}
So the foreach was the issue here trying to call the class function with this. Calling it with the arrow function binds the this or something.... like I said before I prefere the php syntax (or rather Im used to it
Anyway cheers for thinking with me. sure your suggestion would of worked also but thats not what I wanted
But I'm glad you found it for yourself - you will remember far better.
One thing to note. By calling that function from a new instance is rather resource wasteful since every time your node receives a message, your code instantiates a new object that ultimately requires garbage collecting at some point. Making the function static means you do not need to create a new object each time.
PS, stick with the JavaScript/node stuff, once you get familiar, it's not a bad language. I went through a similar pain point as you.
Yup I loaded the new machine bit into the on msg just to test some stuff. I moved it up now so it only gets created once the node is loaded.
I was reading your link on static. so it means that if you use static you have to call the classes name and not the instantiated object anymore?
Example
class name = foo
bar = new foo;
calling bar.somefunctionoffoo
wouldnt work ?
I understand that when it gets instantiated alot there are memory issues. But in my use I moved it up when the node gets instantiated and I dont use it anywhere else but. So only 1 copy of the instantiation exists. Does it still make sense to add static in front of all the functions?
If the method does not use any calls to this. within, then you can tag it as static. But then, you have to use the classname to prefix the method MyClass.callTheFunc(); You can still use this within the static method, but it will refer to the class and static properties and other static methods instead of any instances of the class.
By no means is my code a great example of anything special, but I do make use of classes and have a couple static methods and properties that you can peak at. Maybe a real world usage example might make it a little clearer.
Can you not call a static function using an instance of the object? I know it is not necessary to have an instance, but I would have expected it to work.
You do not have to call it from an instance. Think of how you sometimes may use Date.now() in your code to get a current timestamp. now is a static method of the Date class. Date - JavaScript | MDN
Of course, you would have to require the class to make it available to be able to call its static method if it was defined in some other location.
Sorry for not being clear. A class static method can be called from anywhere, including an instance or some external code. The instance has no special privilege when calling it and must still use the class name prefix.
I think the confusion was when using on or from when stating how the method could be called. Right, the static method cannot be called on an instance, but it can be called from an instance (or anywhere else).
I have to apologise, you are right. I wonder why that is not allowed. In C++ a static method can be called using either the class name or a class instance.