Singletons in Ionic 3, Angular 4

2019-03-23 09:41发布

I am defining service as class, something like this:

@Injectable()
export class MyService {
 ...
}

In other components or pages, I am importing that class with just import command.

import { MyService } from '../pages/services/myservice';

In constructor:

constructor(public _MyService: MyService)

In my main app.module.ts I have added that class service as provider.

providers: [someOtherThings, MyService, someOtherThings]

In Ionic 2, things are working as expected. Service is singleton.

But in Ionic 3, which uses angular 4, it looks like every component is creating new instance of that class.

Is there some new way of creating singleton services classes in angular 4?

3条回答
Juvenile、少年°
2楼-- · 2019-03-23 10:10

Try storing the Service's instance in your AppModule and get the instance (instead of instancing it) later in other components.

import {Injector} from '@angular/core';

export class AppModule {
    // Allows for retrieving singletons using 'AppModule.injector.get(MyService)' later in the code

    static injector: Injector;

    constructor(injector: Injector) {
        AppModule.injector = injector;
    }
}

And to retrive the Service's instance use:

const myService = AppModule.injector.get(MyService);

Check the documentation Here!

查看更多
Bombasti
3楼-- · 2019-03-23 10:21

In my case, it have something to do with ReflectiveInjector.

I have two services A and B, each should be a singleton service referring to each other.

If I inject them in the other's constructor, it may cause compiling error, due to circular reference.

If I use

const injector = ReflectiveInjector.resolveAndCreate([AService]);
const a = injector.get(AService);

in B's constructor, it will make another instance of A.

And is should be solved by making a CService holding the data, and AService and BService can access data through CService.

查看更多
小情绪 Triste *
4楼-- · 2019-03-23 10:30

Im using ionic 3 with lazyload an angular 4 and not having the issues. To make it singleton make sure your app module provide the service. and remove providers on @Component that use the service.

App Module

@NgModule({
  ...

  providers: [
    StatusBar,
    SplashScreen,
    { provide: ErrorHandler, useClass: IonicErrorHandler },
    Singleton // the service or provider to be single ton
  ]
})
export class AppModule { }

The Service

import { Injectable } from '@angular/core';
import 'rxjs/add/operator/map';

@Injectable()
export class Singleton {

  data = "init data";
  constructor() {
    console.log('Hello Singleton Provider');
  }

  set(data){
    this.data = data;
  }

  log(){
    console.log(this.data);   
  }
}

Tes Case the service on ionic page

First Page

import { Component } from '@angular/core';
import { IonicPage, NavController, NavParams } from 'ionic-angular';
import { Singleton } from '../../providers/singleton';

@IonicPage()
@Component({
  selector: 'page-first',
  templateUrl: 'first.html'
})
export class FirstPage {
  constructor(public navCtrl: NavController, public navParams: 
  NavParams,private single:Singleton) {
  }

  ionViewDidLoad() {
    console.log('ionViewDidLoad First');
    this.single.log(); // log init data;
    this.single.set("First singleton data");
  }

}

Second Page

import { Component } from '@angular/core';
import { IonicPage, NavController, NavParams } from 'ionic-angular';
import { Singleton } from '../../providers/singleton';

@IonicPage()
@Component({
  selector: 'page-second',
  templateUrl: 'second.html'
})
export class SecondPage {
  constructor(public navCtrl: NavController, public navParams: 
  NavParams,private single:Singleton) {
  }

  ionViewDidLoad() {
    console.log('ionViewDidLoad Second');
    this.single.log(); // log First singleton data
  }

}

Third Page it create new instance if providers added on component

import { Component } from '@angular/core';
import { IonicPage, NavController, NavParams } from 'ionic-angular';
import { Singleton } from '../../providers/singleton';

@IonicPage()
@Component({
  selector: 'page-second',
  templateUrl: 'second.html',
  providers:[Singleton] // wrong because its create a new instance
})
export class ThirdPage {
  constructor(public navCtrl: NavController, public navParams: 
  NavParams,private single:Singleton) {
  }

  ionViewDidLoad() {
    console.log('ionViewDidLoad ThirdPage');
    this.single.log(); // log init data
  }

}

make sure to remove the providers on component to make it singleton.

查看更多
登录 后发表回答