Call one function from another in custom node - NodeRED - javascript

I am trying to access the function from another file like below:
exp1.js
module.exports = function(RED) {
function expIn(config) {
//some code
}
}
I want to access "expIn()" in another file called exp2.js how can i achieve this??
please help me.

As is, you are not exporting expIn(). You are exporting the outer function in which expIn() is declared and defined. expIn() is just a local variable and cannot be accessed outside of the anonymous outer function you are actually exporting. To make it visible to other files, you either have to export it directly or define it on the exported function.
You're missing some code, but you have 3 options for accessing expIn() outside of exp1.js. First is to export it directly
exp1.js
module.exports = function expIn(config) {
// Code...
};
exp2.js
const { expIn } = require('exp1.js');
expIn({/*config*/});
Alternatively, you could add expIn() to the outer function's prototype. This is usually done when you want to export a class with several methods attached to it. You can do this one of 2 ways. First, the method most similar to what you're already doing is
exp1.js
module.exports = function ClassName(/*constructor args*/) {
this.expIn = function expIn(config) {
// Code...
};
// Other initialization...
};
Alternatively, you could define expIn() more explicitly on the prototype using this method:
exp1.js
function ClassName(/*constructor args*/) {
// Initialize class.
}
ClassName.prototype.expIn = function expIn(config) {
// Code...
};
module.exports = ClassName;
Regardless of which of the 2 methods you choose above, you would access it as
const ClassName = require('exp1.js');
let classInstance = new ClassName();
classInstance.expIn({/*config options/*});
One last method you could use is defining expIn() as a static method on the function class. This would look like:
exp1.js
function ClassName(/*constructor args*/) {
// Initialization code...
}
ClassName.expIn = function expIn(config) {
// Code...
};
module.exports = ClassName;
exp2.js
const ClassName = require('exp1.js');
ClassName.expIn(/*config options*/);

This i resolved by adding function out side the function(RED):
module.exports = function(RED) {
}
function expIn(config) {
//some code
}
And then exported as normal like :
module.exports.expIn = expIn;
then it starts working.
I am not sure whether this is a correct method or not but it serves my requirement.

Related

Exporting multiple functions with arguments

All I am trying to do is to export two functions from a module. One function taking an argument and the other with no argument:
function initClass(params)
{
return new Promise( (resolve, reject) => {
if (!wallet) {
wallet = new WalletClient(params);
resolve(wallet);
} else {
console.log('Wallet is initialized');
resolve(wallet);
}
});
}
function getInstance()
{
return wallet;
}
For initClass(params) only, I can do this as:
module.exports = (params) => {
initClass(params)
}
And then I call this as:
var init = require('./class.js')(params).initClass(params);
This works fine.
Now, for me to export getInstance() as well, I have tried to do the following but it doesn't seem to work.
module.exports = (params) => {
initClass(params),
getInstance
}
This complaints that there is no function getInstance.
Then I tried this:
module.exports.init = (params) => {
initClass(params)
}
module.exports.instance = {
getInstance
}
Then call them as:
var init = require('./class.js').init(params).initClass(params);
What is the proper way to export multiple functions like this?
Thank you.
You're making it more complex than needed. Once you have your functions defined, you can export it with this:
module.exports = {
initClass,
getInstance
}
To use it, you do this:
const init = require("./class.js");
init.initClass(params);
const instance = init.getInstance();
What you're exporting from the module is an object (which I've named init in the example above) that contains two functions. You don't have to pass arguments to the functions at the time you require.
module.exports is basically an object with keys which can refer to any variables/functions of your file.In your case,
module.exports.initClass = function (params){
...
}
module.exports.getInstance = function (){
}
When importing it
var init = require('./class.') // init object has two keys -> initClass and getInstance
init.initClass('abc')
init.getInstance()
If i'm understanding correctly you are trying to export multiple methods if that is the case simple use this.
module.exports = {
method: function() {},
otherMethod: function(parmas) {}
}
In your code use like this.
var init = require('./class.js');
init.method()
init.otherMethond(paramObj)
If you want below scenario you need to check out about method chaining.
var init = require('./class.js').init(params).initClass(params);

Pick the prototype to avoid if-else

The below code snippet I found on one blogs to avoid if-else statement. This code is very modular and can be easily extended. But I am not able to get this to work.
CatModel.prototype.makeWords = function () {
console.log('inside catmodel')
this.setWord('meow')
this.sayIt()
}
DogModel.prototype.makeWords = function () {
console.log('inside dogmodel')
this.setWord('bark')
this.saySomething()
}
// somewhere else
var makeWords = function (type) {
var model = namespace[type + 'Model']
model.makeWords()
}
makeWords('cat')
Presumably the CatModel and DogModel functions are declared somewhere and setWord and sayIt are also set up on their prototype object.
You'd need to put CatModel and DogModel in an object and refer to it from namespace (which I'd recommend not calling namespace):
var namespace = {
CatModel: CatModel,
DogModel: DogModel
};
Then when creating an instance, use new (you always use new with constructor functions). I'd also put the () on the call even though strictly speaking they're optional if you don't have parameters to pass:
var makeWords = function (type) {
var model = new namespace[type + 'Model']()
// ---------^^^--------------------------^^
model.makeWords()
}

Import a function from JS to JSX

I have a JS file containing this code:
module.exports = function loadMyFun() {
function activateSite($currentItem) {
...
}
...
}
And I want to import it into a JSX file, I tried to do it like this but I doesn't work:
import MyNav from './MyNav.js';
const top = MyNav.activateSite();
componentDidMount () {
var self = this;
MyNav.activateSite($(self));
}
...
I get this error:
Uncaught TypeError: _MyNav.default.activateSite is not a function
Any idea how to solve this?
activateSite is a variable that is locally scoped to the loadMyFun function.
It is not available outside the scope of loadMyFun.
It is not a property of the loadMyFun function object.
You cannot access it without rewriting the module.
e.g.
module.exports = function loadMyFun() {
};
module.exports.activeSite = function activateSite($currentItem) {
};
If the code you provided is actually the module you are trying to load, then there are a few problems with that module.
You are exporting a constructor loadMyFun, which you are not calling/instantiating after importing it.
If you would instantiate your constructor like this const myNav = new MyNav() you would have a instance of your exported constructor.
To make your activateSite function work, you would have to assign it to the instance itself and move it out of the local scope of loadMyFunc by assigning it like this: this.activateSite = function(){...}
If you dont need any information wrapped around your activateSite function I would recommend you export an object with your functions instead of the loadMyFun approach.
//myModule.js
module.exports = {
activateSite: function(){ ... }
}
//otherFile.js
import { activateSite } from './myModule.js' // With destructuring
activateSite()
import myModule from './myModule.js' // Without destructuring
myModule.activateSite()

Referencing static method in Class exported from Node JS module

The question is how to refer to other static methods from a static method of a class exported from NodeJS module? Here's a setup. I have following modules: test1.js
var Parent = class {
static smethod1 () {
return this.smethod2();
}
static smethod2 () {
return "Testing tube";
}
}
module.exports = {
Parent:Parent
}
Then I have test2.js that requires this module
var mod = require('./test1');
var Parent = mod.Parent;
module.exports = {
sm1: Parent.smethod1,
sm2: Parent.smethod2
}
Finally, I have a code that is being run in run.js
var test2 = require('./test2');
console.log(test2.sm1());
Naturally, I want to see "Testing tube" line printed out. I am getting error
return this.smethod2();
^
TypeError: this.smethod2 is not a function
Of course, there's shenanigans on NodeJS where this refers to a module, but shouldn't it be referring to a function instead ? Is there way to refer to static method smethod2 from smethod1 with current setup ? If not, what are the workarounds ?
The this keyword is kind of weird in JavaScript, and doesn't always refer to your instance like in most class based languages. In your case, when you call test2.sm1(), this is set to the test2 object, which is
{
sm1: Parent.smethod1,
sm2: Parent.smethod2
}
That object does not have a smethod2 function.
this gets set based on how a function is called in JavaScript, specifically with whatever is before the '.': ->test2<-.sm1().
There are several workarounds. First, after defining the Parent class, you could bind this for that function to the class:
var Parent = class {
static smethod1 () {
return this.smethod2();
}
static smethod2 () {
return "Testing tube";
}
}
// bind `this` to `Parent`
Parent.smethod1 = Parent.smethod1.bind(Parent);
module.exports = {
Parent:Parent
}
Alternatively, you could pass Parent as an argument to call or apply, which sets this manually for just that one invocation:
var Parent = require('./test1');
var test2 = require('./test2');
// call `test2.sm1` with a context of `Parent`
console.log(test2.sm1().call(Parent));

TypeScript call function in dynamic (anonymous) function

I am trying to create a dynamic function in TypeScript which calls an already existing function like:
let dynamicFunction = new Function("existingFunction(\"asdf\");");
function existingFunction(name: string) {
console.log(name);
}
While debugging in chrome dynamicFunction looks like this:
(function() {
existingFunction("asdf");
})
When I try to execute dynamicFunction, it says "Uncaught ReferenceError: existingFunction is not defined", which is no surprise because it's a different scope, but how can I actually call exisitingFunction inside dynamicFunction?
Any help would be greatly appreciated!
Edit:
to be more precise: I've got a typescript file which contains one module.
This module exports a function which should return the created dynamic function.
The created dynamicFunction is then used in another module which actually contains the exisitingFunction.
I've chosen this approach because I need to convert a given string to an executable condition, which will be executed many times.
For example: convert string "VALUE==1" to:
function () {
return exisitingFunction("VALUE") == 1;
}
A short example of how it should look like:
parser.ts:
export module Parser {
export function getFunction(expression: string) {
// Calculating condition...
let condition = "existingFunction(\"VALUE\") == 1;"
return new Function(condition);
}
}
condition.ts:
import { Parser } from "./parser";
class Condition {
// getting the DynamicFunction
private _dynamicFunction = Parser.getFunction("VALUE==1");
someFunctionInsideCondition() {
// Calling the DynamicFunction
this._dynamicFunction();
}
}
// Maybe this function should be somewhere else?
function existingFunction(name: string) {
console.log(name);
return 1;
}
I hope this explains my problem a little bit better.
From the Function documentation
Functions created with the Function constructor do not create closures to their creation contexts; they always are created in the global scope. When running them, they will only be able to access their own local variables and global ones, not the ones from the scope in which the Function constructor was called. This is different from using eval with code for a function expression.
so you'll have to pass existingFunction as an argument or define it in the global space.
try with
var existingFunction = function(name: string) {
console.log(name);
}
Also have a look at eval which will give you access to the current scope ...
--- Update
After the question update and considering your comment about not wanting to use eval because of security concerns (with which i totally agree)
The problem is that in the generated function's scope, this is undefined. Making your existingFunction part of the global scope is already a bad idea and between Typescript and the modules architecture doesn't seem possible at all.
So why not passing a context to the generated function?
This will allow you to control how much of your application to expose to the generated function, while giving it access to external methods.
Something along the lines of:
class Parser {
static getFunction(expression) {
let condition = new Function("context", "context.existingFunction(\"VALUE\") == 1;");
return condition;
}
}
class Condition {
constructor() {
this._dynamicFunction = Parser.getFunction("VALUE==1");
}
someFunctionInsideCondition() {
// Calling the DynamicFunction
this._dynamicFunction(this);
}
existingFunction(name) {
console.log("hello " + name);
return 1;
};
}
let c = new Condition();
c.someFunctionInsideCondition();
Of course your context can be a different object instead of this, where you keep all your utility functions.
I had to donwpile (compile it down, my own word) to es2015 to make the example run here, but I made it originally in Typescript and works fine
I would skip the usage of new Function and instead do it as follows.
The parser.ts file would contain this:
export class FunctionGenerator {
constructor(private fn: Function) {}
makeFunction(args: string): Function {
const [variable, val] = args.split("==");
return () => this.fn(variable) == val;
}
}
This is basically a factory that allows creating a series of functions that call the function passed when the factory is created. You can then use makeFunction for the specific checks you want to perform. (Note that I used == like in your question. I much prefer using === unless there's a reason against it.)
It can then be used like this:
import * as parser from "./parser";
let vars = {};
// This is a simulation of your funciton. It just plucks values from `vars`.
function existingFunction(name: string) {
return vars[name];
}
function resetVars() {
vars = {
"VALUE": 1,
"FOO": 2,
"BAR": 3,
};
}
function test(gen) {
const fn1 = gen.makeFunction("VALUE==1");
console.log(fn1(), "should be true");
const fn2 = gen.makeFunction("BAR==3");
console.log(fn2(), "should be true");
vars["BAR"] = 7;
// Call the same function again, but with a new value in `vars`.
console.log(fn2(), "should be false");
const fn3 = gen.makeFunction("BAR==1000");
console.log(fn3(), "should be false");
}
resetVars();
const gen = new parser.FunctionGenerator(existingFunction);
test(gen);

Categories