Ionic: Service as provider is creating multiple instances

The problem is described in Singletons in Ionic 3, Angular 4 on StackOverflow. It works for Ionic 2 but creates multiple service instances (calling constructor for more than once and data is not shared).

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?

Are you certain that you have no providers in the @Component decorator on any of your pages?

Yes, only in app.module.ts.

Can you please triple-check this? Initially I thought this might be related to lazy loading, but I tested and lazy-loaded pages get shared provider instances.

You mean to check pages/xxx/xxx.ts to make sure there’s no providors? I am sure of that.

check for that in any @Component (not only pages)

I checked, and there’s only in app.module.ts.

Ionic Framework: 3.1.0
Ionic App Scripts: 1.3.6
Angular Core: 4.0.2
Angular Compiler CLI: 4.0.2
Node: 6.10.2
OS Platform: macOS Sierra
Navigator Platform: MacIntel
User Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1

I wrote a test demo and found 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.

I think that’s indicative of a bad design. Two services that are dependent on one another should be combined into a single service.

That being said, you could probably use forwardRef.

Thank you very much for being so helpful! :heart_eyes:

The forwardRef solve my issue when i got the message "Can’t resolve all parameters for page (?)"
I love you <3


    dataBase: DatabaseProvider;
   
    constructor(
                       public navCtrl: NavController, 
                       public navParams: NavParams,
                       @Inject(forwardRef(() => DatabaseProvider)) dataBase : DatabaseProvider,
    ) {
        this.dataBase = dataBase;
    }