Massimo Magliani
Massimo Magliani

Reputation: 647

Angular2, use a service inside another service

Starting from THIS awesome response, I want to use many DataService instances inside another global service (SystemService) that store and serve many "cacheable" datas. I have imported the DataService file and declared the DataService class in the constructor of my global service but at runtime I receive the error "EXCEPTION: No provider for DataService! (AppComponent -> SystemService -> DataService)" Please,can anyone explain how to use that service inside another global service? Thanks so much.

EDIT , code just for example

---------
// inside bootstrap only the single instance of SystemService
....
bootstrap(AppComponent, [ROUTER_PROVIDERS,HTTP_PROVIDERS,SystemService,provide(LocationStrategy, {useClass: HashLocationStrategy})]).
then((appRef: ComponentRef) => {
    appInjector(appRef.injector);
});

-----------
// chacheable and observable generic Data service, I want to use this class in multiple instances one for each cachable and observable data

import {Injectable} from                                'angular2/core';
import {Http, Response,Headers, RequestOptions} from    'angular2/http';
import {Observable} from                                'rxjs/Observable';
import {Observer} from                                  'rxjs/Observer';    
import                                                  'rxjs/Rx'; 
@Injectable(
export class CacheableData<T> {
    private _apiUrl = 'api/apiweb.php';
    private _params:Object;

    public data: Observable<T>; 
    private _dataObserver: Observer<T>;
    private _data:T;

    constructor (private _http: Http){
        this.data = new Observable(observer => this._dataObserver = observer).startWith(this._data).share();
    }   
    public setParams(_params:Object){
        this._params=_params;
    }   
    public getData(refresh:boolean=false) {     
        if (this._data && !refresh) {
            console.log('CacheableData - getData -> Cache',this._data);
            this._dataObserver.next(this._data);       
        } else {            
            console.log('CacheableData - getData -> HTTP...');

            this._http.post(this._apiUrl,
                    JSON.stringify(this._params),
                    new RequestOptions({ headers: new Headers({'Content-Type': 'application/json'})}))          
                .map(res=><T>res.json().data)
                .do((data) => { })     
                .subscribe(res => {
                    // Update cached data
                    this._data = res;                   

                    console.log('CacheableData - getData -> HTTP',this._data);
                    this._dataObserver.next(this._data);
                }, error => console.log('Could not load data.'))                            

        }
    }
}
---------
// the global service used to cache and retrieve certain type of datas from the server
@Injectable()
export class SystemService{
    constructor (public cacheableData1: CacheableData<IData1>,
             public cacheableData2: CacheableData<IData2>) {

        ....
        this.cacheableData1.setParams({
            manager:"ApiManager",
            action:"GetData1",
            WEB_USER_TOKEN:this.user.Token
        });

        this.cacheableData2.setParams({
            manager:"ApiManager",
            action:"GetData2",
            WEB_USER_TOKEN:this.user.Token
        });
        .....

    }
}


---------
// all views can read and observe chached or fresh data using the systemservice
@Component({
    selector: 'home',
    templateUrl:  'app/components/views/home/home.component.html'
})
export class HomeComponent implements OnInit{   
    public data1:IData1;
    public data2:IData2;

    constructor(private _router: Router,                          
            private _systemService: SystemService) {
    }
    ngOnInit(){

        // data1 observable         
        this._systemService.cacheableData1.subscribe(data => this.data1=data);
        this._systemService.cacheableData1.getData();

        // data2 observable         
        this._systemService.cacheableData2.subscribe(data => this.data2=data);
        this._systemService.cacheableData2.getData(true);

    }   
}

Surely I miss something , but the concept is that I need one global instance of SystemService that use multiple instalces of CacheableData service in order to provide observable and cacheable data for all views and pages...or for other services , why not. I cannot add CacheableData to bootstrab because I need multiple instances, but if I don't, I receive the error message that the provider is missing... Excuse me for the incomplete code but my project is quite complex....

Upvotes: 1

Views: 2456

Answers (2)

Nguyễn Việt Trung
Nguyễn Việt Trung

Reputation: 301

Did you check for circulated referencing e.g. Service A uses Service B, and Service B uses Service A? I have recently experienced this kind of issue, and the error message is the same as yours.

Upvotes: 1

Maximilian Riegler
Maximilian Riegler

Reputation: 23506

Every service you want to use, depending on the scope, must be added to a providers array.

Either in the bootstrap call:

bootstrap(AppComponent, [
    ...,
    GlobalService,
    DataService
]);

Or in your root component:

@Component({
    ...,
    providers: [..., GlobalService, DataService]
})
export class AppComponent { ... }

Upvotes: 0

Related Questions