@mpallante wrote:
Hello everyone,
I’m trying to use a LoadingController to show an indicator while I’m doing calls to a remote service, but I have some troubles.
My current situation is the following. I have a
PageComponent
with a simple loading method, something like:export class PageComponent { constructor(private itemsService: ItemsService) { } fillData() { this.itemsService.getItems().subscribe(items => { this.items = items; }); } }
The
ItemsService
is simple too:export class ItemsService { constructor(private http: HttpClient) { } getItems() { let url = 'http://example.org/items/endpoint'; return this.http.get(url).pipe( map(this.buildItems.bind(this) ); } private buildItems(items: any[]) { // convert remote data format to internal one } }
Now I’d like to put a
LoadingController
between the twos, by making both the caller and the callee basically unaware of what’s really happening.So my idea is to create an intermediate service class that’s called from the page class. To make it flexible enough to be used with any kind of service (I have more than
ItemsService
), I tried to pass to the intermediate class the sameObservable
I got from theItemsService
like this:(in
PageComponent
)fillData() { this.loadingService.loadData(this.itemsService.getItems()).subscribe(items => { this.items = items; }); }
and I defined a new service like this:
export class LoadingService { loadData(observable: Observable<any>): Observable<any> { return observable.pipe( finalize(() => { console.log('after data received'); }) ); } }
This code seems to work. When I call the
fillData
inPageComponent
, I get the observable fromItemsService
, add afinalize()
operator to it and finally (infillData()
) I subscribe the observable, having the real remote request called.This way, if I have many services shaped like
ItemsService
, I can dothis.loadingService.loadData(this.service1.getData()).subscribe( /* ... */ ); this.loadingService.loadData(this.service2.getData()).subscribe( /* ... */ ); this.loadingService.loadData(this.service3.getData()).subscribe( /* ... */ ); /* ... and so on */
However, as soon as I add the
LoadingController
inLoadingService
, things go weird. This is how I changed the service:export class LoadingService { private loader = null; constructor(private loadingController: LoadingController) { } loadData(observable: Observable<any>): Observable<any> { this.openLoader(); return observable.pipe( finalize(() => { this.closeLoader(); }) ); } private async openLoader() { if (! this.loader) { this.loader = await.loadingController.create(); } await this.loader.present(); } private async closeLoader() { if (this.loader) { await this.loader.dismiss(); this.loader = null; } } }
Now what I get is that the loading controller actually presents the indicator and usually does not dismiss it after the remote call ends. Sometimes, however, I get the correct behavior: the indicator shows, the call starts, the call ends, the indicator goes away.
I’m not very confident with event-based programming in JS, so it is probably a very stupid question, but I need some help to solve this problem.
Thanks a lot,
Marco
Posts: 1
Participants: 1