I'm trying to create a singleton class so I could avoid opening the same database again.
I've read about creating a class provider with a static variable so it could stay the same, but I've seen that each time I navigate to another component, the static variable content is lost.
Here's my code so far
couchbase.service.ts
import { Injectable } from "@angular/core";
import { Couchbase } from "nativescript-couchbase";
import * as connection from "tns-core-modules/connectivity";
import { isAndroid } from "platform";
@Injectable()
export class CouchbaseService {
private static database: any;
constructor() {
console.log("enter constructor")
}
public static init(){
if(!CouchbaseService.database) {
console.log("enter init")
CouchbaseService.database = new Couchbase("data");
}
return CouchbaseService.database;
}
public getDatabase() {
return CouchbaseService.database;
}
...
}
app.component.ts
: I've read that calling init
from this parent class would make the app keep it for the children (note that I also tried passing the CouchbaseService
as a constructor parameter, changing the method init
to non-static)
import { Component } from "@angular/core";
import * as Platform from "platform";
import { CouchbaseService } from './services/couchbase.service';
@Component({
selector: "ns-app",
templateUrl: "app.component.html",
})
export class AppComponent {
constructor() {
CouchbaseService.init();
}
}
In my app.module.ts
file, I added CouchbaseService
to the providers
list.
import { NgModule, ErrorHandler, NO_ERRORS_SCHEMA } from "@angular/core";
import { NativeScriptModule } from "nativescript-angular/nativescript.module";
import { NativeScriptUIListViewModule } from "nativescript-ui-listview/angular";
import { NativeScriptUISideDrawerModule } from "nativescript-ui-sidedrawer/angular";
import { NativeScriptHttpModule } from "nativescript-angular/http";
import { Http } from "@angular/http";
import { NativeScriptUIDataFormModule } from "nativescript-ui-dataform/angular";
import { NativeScriptFormsModule } from "nativescript-angular/forms";
import { registerElement } from 'nativescript-angular/element-registry';
import { CardView } from 'nativescript-cardview';
import { AppRoutingModule } from "./app.routing";
import { AppComponent } from "./app.component";
import { CouchbaseService } from "./services/couchbase.service";
import { HomeComponent } from "./components/home/home.component";
registerElement('CardView', () => CardView);
registerElement("MapboxView", () => require("nativescript-mapbox").MapboxView);
registerElement("Fab", () => require("nativescript-floatingactionbutton").Fab);
@NgModule({
bootstrap: [
AppComponent
],
imports: [
NativeScriptModule,
NativeScriptUIListViewModule,
NativeScriptUISideDrawerModule,
AppRoutingModule,
NativeScriptUIDataFormModule,
NativeScriptFormsModule,
NativeScriptHttpModule
],
declarations: [
AppComponent,
HomeComponent
],
providers: [
CouchbaseService,
],
schemas: [
NO_ERRORS_SCHEMA
],
entryComponents: [
],
})
/*
Pass your application module to the bootstrapModule function located in main.ts to start your app
*/
export class AppModule { }
When I look at the logs in the terminal, seems like each time I navigate to another component the service is restarted, so it looses the value of database
.
I'm using NativeScript 4 with Angular 5 and TypeScript 2.7.2.
This is not how should make use of a singleton service. Let's do this way:
Change your service like this:
import { Injectable } from "@angular/core";
import { Couchbase } from "nativescript-couchbase";
import * as connection from "tns-core-modules/connectivity";
import { isAndroid } from "platform";
@Injectable()
export class CouchbaseService {
private database: any;
constructor() {
console.log("enter constructor")
this.init();
}
private init(){
if(!this.database) {
console.log("enter init")
this.database = new Couchbase("data");
}
}
public getDatabase() {
return this.database;
}
...
}
In your AppModule
[or module where you have your service] specify the service in @NgModule
's provider array like this:
@NgModule({
declarations: [
AppComponent,
YourComponent
],
imports: [
BrowserModule
],
providers: [CouchbaseService],
bootstrap: [AppComponent]
})
export class AppModule { }
Now in your component use constructor dependency injection like this:
import { Component } from "@angular/core";
import * as Platform from "platform";
import { CouchbaseService } from './services/couchbase.service';
@Component({
selector: "ns-app",
templateUrl: "app.component.html",
})
export class AppComponent {
constructor(private service: CouchbaseService) {
console.log(this.service.getDatabase());
}
}