Using class object from diffrent class - javascript

I’m having type script class which expose some service list
I’ve defined a property that should have reference to the ServiceCatalog class like following:
export default class myGenerator extends Generator {
private svcat: ServiceCatalog | undefined;
// and here I’ve initilzied the property
await this.getSvc();
// here I created some function the return service instances
private async getSvc() {
this.svcat = new ServiceCatalog();
await this.svcat.getServiceInstances();
}
// and here I’ve additional code which use it
this.svcat.values ….
My question is there Is a better/cleaner way of doing the in javascript/typescript ?
maybe not using the this keyword...
And also maybe a better code for testing (unit-test) ...

The way you are doing today, it is very hard to test. Why is that? Well, because if you want to isolate your Generator class from your ServiceCatalog, you will have a hard time.
What I suggest, like the colleague above, is to have the ServiceCatalog coming by customer BUT have a default value.
class MyGenerator extends Generator {
constructor(private svCat: ServiceCatalog = new ServiceCatalog()) {
super();
}
}
This way you can use it normally like
new MyGenerator()
or for testing
new MyGenerator(myFakeServiceCatalog)

Inject the Service into your myGenerator class.
Add this to your constructor:
constructor(private svcat:ServiceCatalog) {}
You can now access the injected Service using
await this.svcat.getServiceInstances();
There is no need to add a property (your svcat:ServiceCatalog|undefined part) for the service.
"this" is needed a lot in java/type-script since it refers to the current class.

Related

Extend NestJS decorator

I stumbled across this question but I don't think I want to use an alias
I want to extend the express anyFilesInterceptor so I can work with a custom file object. I am not sure how to extend a decorator in NestJS.
So as a work around I tried decorator composition from another question. However, I am getting an error just trying to create a very basic (example in documentation) decorator
import { applyDecorators, createParamDecorator, ExecutionContext } from "#nestjs/common";
import { AnyFilesInterceptor } from "#nestjs/platform-express";
export function Test() {
return applyDecorators(
AnyFilesInterceptor,
TestDecorator
)
}
export const TestDecorator = createParamDecorator(
(data: string, ctx: ExecutionContext) => {
const request = ctx.switchToHttp().getRequest();
const user = request.user;
return data ? user?.[data] : user;
},
);
Now I can see from other discussions and the function naming that AnyFilesInterceptor is a mixin that returns a class while TestDecorator created by createParamDecorator likely only works on parameters.
Does NestJS have a way to create a class decorator? Or to extend existing decorators?
actually the AnyFilesInterceptor is a function itself that produces an interceptor (which is any class that implements NestInterceptor).
You can see it by the usage: while 'other' interceptors may be used by simply giving the class to the UseInterceptor() decorator, this interceptor needs invocation (without new keyword).
Example:
#UseInterceptor(RegularInterceptor)
//or
#UseInterceptor(new RegularInterceptor())
// AnyFilesInterceptor is a function returning a class
#UseInterceptor(AnyFilesInterceptor())
//or
#UseInterceptor(new (AnyFilesInterceptor())({/* some multer options here */))
so basically if you want to extend the AnyFilesInterceptor you simply need to define a class inteceptor of your own:
export class MyAllFilesInterceptor extends AnyFilesInterceptor() {
// YOU MUST OVERRIDE THE `intercept` METHOD!
// also, give options to the `AnyFilesInterceptor` method if you wish
}

Angular like dependency injection of services in Javascript

I am writing a Javascript npm package. In my code I have a single class which I want to act like an angular service. Only one instance of that class should be created and needs to be shared wherever wanted in the project.
//this class object would be shared across project and only one object can be created. also, its implementation could change in future
export class SharedClass {
constructor(somethingImp) {
}
//more methods
}
export class ProjectClass1ThatNeedsSharedClassObj {
//it should get the required object
}
export class ProjectClass2ThatNeedsSharedClassObj {
//it should get the required object
}
How can I write a simple DI to achieve this functionality?
If you want enforce a single object through all methods of DI, you can use a static variable. This is the pattern I normally use
export class SearchProvider {
private static _default: SearchProvider
constructor() {
}
static get Default() {
return this._default || (this._default = new SearchProvider())
}
}
export class Consumer() {
private SearchProvider _provider = SearchProvider.Default;
}
1)Create that class as a service with #Injectable decorator
2)Import that class into class where you want to use it
3)create a instance of service class into that class
4)now you can access methods of service class using instance created in constructor
using this keyword & . operator
5)You have to write service class once & use it many times as you want
Happy coding

maintaining a JS scope in a Custom Element constructor call

I am experimenting with a new pattern,
where each newly created Card element
uses the constructor scope to store (private) variables:
pseudo code:
class CardtsCard extends HTMLElement {
constructor(){
let private = 666;
Object.assign(this,{
getPrivate : () => console.log(private)
});
}
get private(){
//can not access scope in constructor
return 42;
}
}
So:
el.getPrivate(); // outputs 666
el.private; // outputs 42
I have loads of getters and setters
and sticking data ON my elements with this.whatever=value feels a bit weird.
I can extend it to:
class CardtsCard extends HTMLElement {
constructor(){
let private = new Map();
Object.assign(this,{
setPrivate : (data,value) => private.set(data,value),
getPrivate : (data) => private.get(data)
});
}
}
Question: I am no JS scope expert, are there drawbacks?
Whenever you call the constructor in the first example, a closure has to be created which contains these "private" variables. For a few elements that doesn't cause any overhead, but for a lot of elements you might see a performance and memory overhead.
Concerning your second example: Map lookups can't be inlined, property lookups can, so they are way more performant (which you will only notice on many operations).
And what benefit do you have through this setup? A public method getPrivate isn't really private isn't it? If you need private variables, mark them as private in some way, and trust everyone using the code to deal with it appropriately.

How to call a class methods in JavaScript

I am currently learning ES6. While I was playing with the new features, I got stuck at one point. How to call a class method.
So let's say I have a class in one file like below:
class Auth {
checkUserSignedIn() {
//check user signed in
}
signupUser(account) {
//signup user
}
loginUser(account) {
//login user
}
getCurentUser() {
//Current User
}
}
module.exports = Auth;
and then in some other file, let's say a controller I would like to call these functions.
const Auth = require('./auth');
class Controller {
signupUserUsingEmailAndPass(user) {
Auth.signupUser(account);
}
loginUserUsingEmailAndPass(account) {
Auth.loginUser(account);
}
isUserSignedIn() {
checkUserSignedIn();
}
}
module.exports = Controller;
But this doesn't work at all. I guess there is something I am not understanding correctly. Any suggestion/advice?
Methods defined in a class require an instance of that class, i.e. a new Auth somewhere.
Your controller should be defined has
class Controller {
constructor(auth) {
this.auth = auth;
}
}
This approach over the require('myclass') allows for you to inject different implementations of your Auth class.
Should you not desire an instance of Auth for those methods, declare them as static. More on that here
You need to either instatiate the Auth
const authorization = new Auth();
Possibly inside the file containing the Auth class, and just export the instance.
export const authorization = new Auth();
Or, if You want this methods available outside. You can make the methods static. Just add static keyword before the method name during method creation.
You can read more about static methods here
Javascript classes don't work quite like the module pattern (that it seems) you're used to. When you export `Auth, you're exporting the class definition but you still need to instantiate it.
let auth = new Auth()
auth.signupUserUsingEmailAndPass() // or any other function you define
In javascript, a class is useful when you want to populate it with data or some sort of state. If you don't want or need that then you can use a module.

Overidding library function in es6

I'm trying to override specific function in a library.
In my case, I'm trying to override some functions on Framework7. The library simply has class called Framework7, in non ES6 javascript, creating instance of application would look like this:
var app = new Framework7();
so I assume it's extendable, so here my code to extends it:
export class Application extends Framework7 {
constructor(options) {
super(options);
}
}
the code run fine, however, when I try to override one of the function, let say showPreloader, the function itself is never called
export class Application extends Framework7 {
constructor(options) {
super(options);
}
showPreloader(title) {
console.log('this not printed :(');
super(title); // this is not called as well
// but showPreloader() from Framework7 still called
}
}
I also try different approach to override it, i come with a solution like this:
export class Application extends Framework7 {
constructor(options) {
super(options);
this.showPreloader = (title) => {
console.log('print me!'); // printed! :D
super(); // oh, wait! cannot call super from here! :(
}
}
}
However, it looks a bit ugly and I cannot call super from there.
Is there any workaround so I can override a function from library and calling the base function via super (or anything?)
I assume it's extendable
Don't. Read the docs, ask the authors, or read the source yourself.
In your case, the library you've chosen doesn't exactly follow best practises, it just installs its methods directly on the app "instance". It's a factory function, not a constructor.
Is there any workaround so I can override a function from library and calling the base function?
Yes, by storing the original method in a variable before overwriting it. You then can call it using .call(this) (like inheritance was done in ES5).
…
const original = this.showPreloader;
this.showPreloader = (title) => {
console.log('print me!'); // printed! :D
original.call(this, title);
}
However, that's no fun, especially since it's not just a few instance-specific methods but actually all of them. So you'd better drop ES6 class syntax and "subclassing" here, and use a parasitical inheritance approach instead:
function MyFramework7(options) {
const app = new Framework7(options);
const {showPreloader, …} = app; // all the original methods
… // mess with the object to your liking
return app;
}
Or maybe you don't even need to wrap it in a function, as app is a singleton I guess.

Categories

Resources