How to create a singleton observable? - javascript

I have a singleton class :
let instance = null;
class SingletonClass {
constructor() {
if (!instance) {
instance = this;
}
return instance;
}
get types() {
return this._types;
}
set types(value) {
this._types = value;
}
}
export default SingletonClass;
and i use it like this:
import SingletonViews from './SingletonClass';
export default class MyStore {
this._singletonClass = new SingletonClass();
#observable types;
this.types= this._singletonClass.types; //i dont know what to do here to bind this two together
}
But whenever this._singletonClass.types updated the types observable wont. what can i do about it?
can i have a #observable singleton or can i bind its proprty to a #observable

Your "singleton" is not an observable itself and what is your intention? just proxy the singleton values?
Since you don't seem to need to initialize your singleton, I'd rewrite it this way:
Singleton
import * as mobx from 'mobx'
const {observable, action} = mobx
class SingletonClass {
#observable types
#action setTypes (value) {
this.types = value;
}
}
export default new SingletonClass()
MyStore
import singletonClass from './SingletonClass'
export default class MyStore {
singletonClass = singletonClass
}
Now you can use your store somewhere in your app and observe your singleton.

Related

Angular - I want to split a service into several services but share the same data

I have a service that is 1000 lines long, I would like to split it into several services but I need to share some data between these different services.
#Injectable()
export class ServiceParent {
toto = new Toto(),
}
#Injectable()
export class ServiceChild extend ServiceParent {
init() {
this.toto.doSomething();
}
}
#Component()
export class myComponent {
ngOnInit() {
console.log('this.ServiceChild.init()') // return undefined
}
}
How to solve this problem ?
Thanks ^^
Simply create a global variable.
let toto = new Toto();
#Injectable()
export class Service1 {
init() {
this.toto.doSomething();
}
}
#Injectable()
export class Service2 {
init() {
this.toto.doSomething();
}
}

'this' returns undefined in extended Classes in Javascript

I am trying to run the code below, but it is not working. I think this is a scope problem, but I'm not sure how to fix this.
import CommonController from './CommonController';
import CategoryService from './category/Service.js';
class CategoryController extends CommonController {
constructor() {
super(CategoryService);
}
}
export default new CategoryController();
// ===================CommonController==========================
export default class CommonController {
constructor(service) {
this.service = service;
}
async get () {
console.log(this); // it returns undefined
}
}
// ===================CategoryService==========================
import Category from './Category'
import dto from './dto'
class CategoryService extends CommonService {
constructor() {
super(Category, dto);
}
}
export default new CategoryService();
// ===================CommonService==========================
export default class CommonService {
constructor(model, dto) {
this.model = model;
this.dto = dto;
}
}
if a run:
import CategoryController from './CategoryController';
CategoryController.get()
the console.log in CommonController get function will print undefined
Am I doing something wrong?
The issue is that you are calling get() on the class itself, instead of calling it on an instance of the class. Try creating an instance of CategoryController, like so:
cc = new CategoryController();
Then, you should be able to call:
cc.get();
Demo in the code below (same as yours, just slightly modified to reflect my point).
// ===================CommonController==========================
class CommonController {
constructor(service) {
this.service = service;
}
async get () {
console.log(this); // it returns undefined
}
}
// ===================CommonService==========================
class CommonService {
constructor(model, dto) {
this.model = model;
this.dto = dto;
}
}
// ===================CategoryService==========================
class CategoryService extends CommonService {
constructor() {
super(Category, dto);
}
}
class CategoryController extends CommonController {
constructor() {
super(CategoryService);
}
}
cs = new CategoryController();
cs.get();

ES6 importing extended classes

So I have come across an interesting issue while trying to extend a class to use in another class and then import it to another file.
'class-test.js':
export default class MyClass {
constructor () {
this.date_created = new Date()
this.posts = new Posts()
}
}
class Posts extends Array {
add (val) {
this.push(val)
}
}
Then when I create a new MyClass instance in another file (and import MyClass from class-test.js), the myClass.posts property is only being seen as an Array and so doesn't have the extended function add()
I think the problem is that the Posts class is not being moved with the MyClass class; but without casting I have no idea how to tell it to use that class.
Where I'm particularly frustrated is it works fine if all in one file:
class MyClass {
constructor () {
this.date_created = new Date()
this.posts = new Posts()
}
}
class Posts extends Array {
add (val) {
this.push(val)
}
}
var x = new MyClass('as', 'asd')
x.posts.add('asdf')
console.log(x.posts)
x.posts.add('qwer')
x.posts.add('zxcv')
console.log(x.posts)
Did you try to export, and import both classes ?
'class-def.js':
class MyClass {
constructor () {
this.date_created = new Date()
this.posts = new Posts()
}
}
class Posts extends Array {
add (val) {
this.push(val)
}
}
export { MyClass, Posts };
'class-test.js':
import { MyClass, Posts } from 'class-def.js';
var x = new MyClass('as', 'asd')
x.posts.add('asdf')
console.log(x.posts)
x.posts.add('qwer')
x.posts.add('zxcv')
console.log(x.posts)

React native and MobX: How to create a global store?

I am currently trying to implement a mobx storage which I can call from everywhere like so:
import {userStore} from '../UserStore.js';
At the end of the file, my export functionality looks as follows:
const userStore = new UserStore();
export {userStore};
As I understand, everytime I call the import functionality, the object gets re-created with which multiple files that import UserStore don't share the same variables.
However, I want that every file that imports UserStore imports the same object with the exact same variables. How can I achieve this? I am not fully sure how to achieve, so any ideas and examples would be appreciated :)
The full code (for the UserStore.js declaration), if of any help, is as follows (look at the very bottom for the export statement)
import {observable, computed, action} from 'mobx';
import {ObservableMap, toJS} from 'mobx';
import {Fb} from './firebase.js';
class UserStore {
/** GPS */
#observable usrLng = 0.0;
#observable usrLat = 0.0;
#observable watchID = null;
#action
watchCurLocation() {
this.watchID = navigator.geolocation.watchPosition((position) => {
console.log("Recording GPS data from within the Store!!");
this.usrLat = parseFloat(position.coords.latitude);
this.usrLng = parseFloat(position.coords.longitude);
}, (error) => console.log(JSON.stringify(error)), {
enableHighAccuracy: true,
timeout: 2000,
maximumAge: 1000
});
}
#action
clearWatch() {
navigator.geolocation.clearWatch(this.watchID);
}
/*/ GPS */
/** BIKE BOOKING */
#observable interestBikeNo = -1;
#observable bookedBikeNo = -1;
#action
setInterestBikeNo(bn) {
this.interestBikeNo = bn;
}
}
const userStore = new UserStore();
export {userStore};
You simply need a singleton instance of UserStore class
Sample demo
let localInstance = null;
export class Apple {
static newInstance() {
if (! localInstance)
localInstance = new Apple();
return localInstance;
}
}
// usage
import {Apple} from './apple';
const instance = Apple. newInstance();
In your case, you can use a simple function
import {observable, computed, action} from 'mobx';
import {ObservableMap, toJS} from 'mobx';
import {Fb} from './firebase.js';
class UserStore {
// omitted
}
let userStore;
export function getUserstore() {
if (!userStore)
userStore = new UserStore();
return userStore;
};
Somewhere in code
// instead of
import {userStore} from './someUserStoreModule';
// use
import {getUserstore} from './someUserStoreModule';
const userStore = getUserstore();

Dependency Injection Constructor that takes arguments

I'm building an Aurelia app that uses "Models" for every type of data object.
All my Models look something like this:
export class Item {
id = null;
name = '';
description = '';
constructor (data) {
Object.assign(this, data);
}
}
And I later create objects like this:
export class SomeViewModel {
activate () {
this.myItem = new Item({
name: 'My Item!',
description: 'This is my item. It will be initialized with these properties.'
});
}
}
I got the Object.assign() bit from an article I read and it works really well. It allows me to create new items using data from the server, or if I want an empty Item I simply don't pass in anything.
Now I've reached a point where I need my model to have access to another class so I'm using Aurelia's Dependency Injection like this:
import {inject} from 'aurelia-framework';
import {Router} from 'aurelia-router';
#inject(Router)
export class Item {
id = null;
name = '';
description = '';
constructor (router, data) {
this.router = router;
Object.assign(this, data);
}
get permalink () {
return window.location.protocol + '//' + window.location.host + this.router.generate('item', {itemId: this.id});
}
}
Now my problem is this; how do I create a new Item() without passing in the Router myself? I guess switching the order of argument to constructor() would do the trick but that doesn't seem to work with Aurelia?
And I don't want to have to do this every time I create a new Item:
import {inject} from 'aurelia-framework';
import {Router} from 'aurelia-router';
#inject(Router)
export class SomeViewModel {
constructor (router) {
this.router = router;
}
activate () {
this.myItem = new Item(this.router, {
name: 'My Item!',
description: 'This is my item. It will be initialized with these properties.'
});
}
}
Surely there must be a better way to solve this?
Use the Factory resolver. Here's an example: https://gist.run?id=46642ac54893186067e7cd890d6722a3**
import {inject, Factory} from 'aurelia-dependency-injection';
import {MyModel} from './my-model';
#inject(Factory.of(MyModel))
export class App {
message = 'Hello World!';
constructor(createModel) {
let model = createModel('my data');
}
}
my-model.js
import {inject} from 'aurelia-dependency-injection';
import {EventAggregator} from 'aurelia-event-aggregator';
#inject(EventAggregator)
export class MyModel {
constructor(eventAggregator, data) {
console.log(eventAggregator, data);
}
}

Categories

Resources