Nodejs Calling the class multiple times - node.js

I have simple class like that;
class Foo {
constructor() {
this.datas = {}
}
set(key, data) {
return this.datas[key] = data
}
get(key) {
return this.datas[key]
}
}
module.exports = Foo
I am adding some data to datas veriable first. But when I call same class in the next time, veriable is not saving like that;
const foo1 = Foo()
foo1.set('a',[1,2,3])
const foo2 = Foo()
var aData = foo2.get('a')
console.log(aData)
But data not getting. How can I fix it?

The datas property that you defined in the Foo class is not being saved between instances of the class, because it is defined inside the constructor function. This means that every time you create a new Foo object with const foo = new Foo(), a new datas property will be created for that object, and it will not be shared with other instances of the Foo class.
if you want to shared by all instances of the class.refer Javascript ES6 shared class variable

You can pass your object into another class constructor,
https://stackblitz.com/edit/node-k3vqtp?file=index.js
or use global variable
global.foo = new Foo();
global.foo.set('a', [1, 2, 3]);
or use package like InversifyJS to inject the class
...
#injectable()
export default class A implements IA {
private _foo!: Foo;
public get foo(): Foo {
return this._foo;
}
public set foo(v: Foo) {
this._foo = v;
}
constructor(
#inject(TYPES.Foo) foo: Foo,
) {
this.foo = foo;
}
...
Due to the limited information from your question, here only list some options. You can look for the best way to fit your scenario.

Related

Get filename of derived class from base class in typescript running on node.js?

I'm looking for a way to get the filename of a derived class from a base class in typescript running on node.js. An example of this would be:
Foo.ts
export abstract class Foo {
constructor() { }
name() { return (__filename); }
print() { console.log(this.name()); }
}
Bar.ts
import { Foo } from './Foo';
export class Bar extends Foo {
constructor() { super(); }
}
main.ts
import { Bar } from './Bar';
let bar = new Bar();
bar.print(); // should yield the location of Bar.ts
Due to the number of files involved and just cleanliness I'd like this to be confined to the Foo class rather than having an override of the name() function in each derived class.
I was able to sort-of solve this with the code:
private getDerivedFilePath(): string {
let errorStack: string[] = new Error().stack.split('\n');
let ret: string = __filename;
let baseClass: any = ThreadPoolThreadBase;
for (let i: number = 3; i < errorStack.length; i++) {
let filename: string = errorStack[i].slice(
errorStack[i].lastIndexOf('(') + 1,
Math.max(errorStack[i].lastIndexOf('.js'), errorStack[i].lastIndexOf('.ts')) + 3
);
let other: any = require(filename);
if (other.__proto__ === baseClass) {
ret = filename;
baseClass = other;
} else {
break;
}
}
return (ret || '');
}
Added to Foo, which will work when called from the constructor to set a private _filename property, for inheritance chains beyond the example above so long as the files are structured with a default export of the class being used. There may also be a caveat that if a base class from which a derived object is inheriting directly is initialized as a separate instance within the constructor of any member of the inheritance chain it could get confused and jump to another independent derived class - so it's a bit of a hacky work-around and I'd be interested if someone comes up with something better, but wanted to post this in case someone stumbles across this question and it works for them.
You can use require.cache to get all cached NodeModule objects and filter it to find your module.
https://nodejs.org/api/modules.html#requirecache
class ClassA {
public static getFilePath():string{
const nodeModule = this.getNodeModule();
return (nodeModule) ? nodeModule.filename : "";
}
public static getNodeModule(): NodeModule | undefined{
const nodeModule = Object.values(require.cache)
.filter((chl) => chl?.children.includes(module))
.filter((mn)=> mn?.filename.includes(this.name))
.shift();
return nodeModule;
}
}
class ClassB extends ClassA {
constructor(){}
}
const pathA = ClassA.getFilePath(); //Must return the absolute path of ClassA
const pathB = ClassB.getFilePath(); //Must return the absolute path of ClassB

How to use class functions in another class?

How can i use class instance in another class like a pointer in C++ to class instance functions?
Example:
class A {
constructor()
{
this.block = [];
}
method()
{
return this.blocks.length;
}
}
another class:
class B {
constructor(instance)
{
this.instance = instance;
}
method()
{
this.instance.method(); // here i'm getting cannot get length of undefined
}
}
If i'm trying to to like that i'm getting problems to call it
You can try this. Here, when creating B class's instance I give into it an A class's instance as argument. Then inside B we can call A instance's methods, and access its properties.
Also, as #ViaTech posted you can use static methods to access them without needing to initialize an object of the class. That is what static methods is. Refer Static Methods
class B {
constructor(instance)
{
this.instance = instance;
}
method()
{
this.instance.method();
}
}
class A {
constructor()
{
}
method()
{
console.log("A's method");
}
}
var a = new A();
var b = new B(a);
b.method(); // A's method
You can easily do this in JS by calling a static method like so:
class A {
static write(){ //static method
console.log("Called write from A");
}
}
class B {
doIt(){
A.write();
}
}
let b = new B();
b.doIt();
Option 2, you instantiate the class in the constructor of the other like so:
class A {
write(){
console.log("Non-static write() called from class A");
}
}
class B {
constructor() {
this.a = new A();
}
doIt(){
this.a.write();
}
}
let b = new B();
b.doIt();
There are a few ways:
I accidentally switched between PHP and Javascript, but the principles are the same for both)
Use static functions:
Normally, you have a this in the class. Say you have this code:
class Car {
let color;
public function setColor(newColor){ this.color = newColor;}
}
let car = new Car();
car->setColor('green')`
The setColor function's this refers to that car. You can make let anotherCar = new Car(), then when you do anotherCar->setColor('red') you only change that car, not the first one. Simplistic: You can create multiple instances.
If you do not need that, but need the class once, you can make it static. A simple way to explain would be "you have a collection of seperate functions, just put into a wrapping class (which doesn't do a lot really)". For instance, you might have some sanatizing methods:
class Sanitize {
static function makeHtmlSave(input){
return doYourMagicHere(input);
}
static function removeXssCode(input){
return doMoreMagicHere(input);
}
}
This way, you can reuse it multiple times. If you want to use it, you do Sanitize::makeHtmlSave(someCode) where you need it. There isn't a Sanitize thing, it's just a wrapper to access the frunctions inside it.
Use extend:
You can extend a class. Say you have a generic class Vehicle, which has some properties (eg a motor, numberWeels, color) and you can extend that with more specific classes:
class Vehicle {
let color;
public function setColor(newColor){ this.color = newColor}
}
class Car extends Vehicle {
let hasAirco = false;
public function hasAirco(newValue){ this.hasAirco = newValue};
}
If you do let car = new Car(), you get a Car object, that extends/enlarges/complements the Vehicle class, so you can use both its (public) functions. Internally, Car can use the functions of Vehicle too.
Just pass it
class One {
// some stuff
}
class Two{
let otherObject;
construct(givenObject){
this.otherObject = givenObject;
}
}
You can now do this let a = new One(); let b = new Two(a);. You can not use the functions of One inside Two, but you can still use a->doSomething(). This solution feels like the easiest, but it almost never is. Classes/objects are tricky stuff, but I've rarely uses this solutions. There are use cases, but often it's a bad smell indicator.

declare 'this' value for helper function

I have a class:
const helper = function(val){
console.log(this.a);
console.log(this.b);
this.bar();
};
export class Foo {
public b = '45'
private a = 15;
bar(){
}
myMethod(){
return helper.apply(this,arguments);
}
}
the problem is, in the helper function, it doesn't know what the context is (what the value of 'this' is).
Is there a way for me to tell typescript that the value for this in the helper function is an instance of Foo?
(the reason I use the helper function is to create true private methods).
Try adding this on top of your helper function:
let self: Foo = this as Foo;
// use self instead of this below
Alternatively, you could replace all instances of this in it with (this as Foo).
You can declare the type of this for any function by adding an extra parameter named this. The this parameter will not be emitted to Javascript, it will be just for the benefit of the compiler to be able to type check your code:
const helper = function(this: Foo, val: number){
console.log(this.a); /// error a is private
console.log(this.b);
this.bar();
};
This will not however break encapsulation, you will still not be able to access private properties from outside the class, so unless you create the function inside the class it will still give an error as above. For functions defined inside the class it will not give errors:
export class Foo {
public b = '45'
private a = 15;
bar() { }
createHelper() {
return function (this: Foo, val: number) {
console.log(this.a);
console.log(this.b);
this.bar();
};
}
myMethod() {
return this.createHelper().apply(this, arguments);
}
}

constraint on static fields and type inference

Is it possible to have constraint on static fields in Haxe? For example we may have classes which have static field instance of type of corresponding class. And we may want a function that will return an instance of class passed as parameter. This is my attempt:
class Foo {
static public var instance = new Foo();
function new() {}
}
class Test {
// get instance from every class that have static field instance
static function getInstance<T, ClassT:({instance:T}, Class<T>)>(t:ClassT):T {
return t.instance;
}
static function main() {
var a = getInstance(Foo);
$type(a); //Test.hx:14: characters 14-15 : Warning : Unknown<0>
}
}
but it fails, because type parameter constraints are checked lazily. Any ideas on how do this?
Have you considered using a typedef?
Heres a quick edit of your code showing the basic idea
typedef HasInstance = {
var instance:Dynamic;
}
class Foo {
static public var instance = new Foo();
function new() {}
}
class Bar {
static public var instance = new Bar();
function new() {}
}
class Test {
// get instance from every class that have static field instance
static function getInstance<T:HasInstance>(t:T):T {
trace(t);
return t.instance;
}
static function main() {
var a = getInstance(Foo);
trace(a);
$type(a);
var b = getInstance(Bar);
trace(b);
$type(b);
}
}
example on try haxe!
You would change the instance type within the typedef to be more appropriate for your needs, and you can also constrain typedefs too, which can be very useful
If you don't mind using macro, here is a possible solution:
http://try-haxe.mrcdk.com/#7d650
Foo.hx
class Foo {
static public var instance = new Foo();
public var foo:Int;
function new() {}
}
class Test {
macro static function getInstance(e) return Macro.getInstance(e);
static function _getInstance<T, ClassT:({instance:T}, Class<T>)>(t:ClassT):T
return t.instance;
static function main() {
var a = getInstance(Foo);
$type(a);
}
}
Macro.hx
import haxe.macro.Expr;
import haxe.macro.Context.*;
using tink.MacroApi;
class Macro {
public static function getInstance(e:Expr) {
var ct = TPath(e.toString().asTypePath());
return macro (Test._getInstance($e):$ct);
}
}

Can Xamarin create an object instance by class name?

In Xamarin Android, is it possible to create an instance of an object from the class name?
For example if my class is Foo, I would like to do this:
ObjectHandle handle = (Foo)System.Activator.CreateInstance(null, "Foo");
Foo foo = (Foo)handle.Unwrap();
foo.PartyOn();
The class Foo is in the same project (the main App) which is why I'm passing null to CreateInstance.
This code produces a TypeLoadException: "Could not load type 'Foo'.
You need to qualify the namespace for Foo:
namespace MyApp
{
public class Foo
{
public void PartyOn()
{
Console.WriteLine ("Party party!");
}
}
// ...
var handle = Activator.CreateInstance(null, "MyApp.Foo");
Foo foo = (Foo)handle.Unwrap ();
foo.PartyOn();
}

Resources