我使用Angular7 / Ionic4重建的旧应用程序有问题。
在尝试调用远程服务时,我试图使用LoadingController来显示指示器,但是我遇到了一些麻烦。
我目前的情况如下。我有一个带有简单加载方法的PageComponent
,类似:
export class PageComponent {
constructor(private itemsService: ItemsService) { }
fillData() {
this.itemsService.getItems().subscribe(items => {
this.items = items;
});
}
}
ItemsService
也很简单:
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
}
}
现在,我想通过使呼叫者和被呼叫者基本上都不知道实际发生的事情,在两者之间加上LoadingController
。
所以我的想法是创建一个从页面类调用的中间服务类。为了使其具有足够的灵活性以用于任何类型的服务(我拥有超过ItemsService
的服务),我尝试将与Observable
类似的ItemsService
传递给中间类,例如这个:
(在PageComponent
中)
fillData() {
this.loadingService.loadData(this.itemsService.getItems()).subscribe(items => {
this.items = items;
});
}
我定义了这样的新服务:
export class LoadingService {
loadData(observable: Observable<any>): Observable<any> {
return observable.pipe(
finalize(() => {
console.log('after data received');
})
);
}
}
此代码似乎有效。当我在fillData
中调用PageComponent
时,我从ItemsService
中得到了可观察对象,并向其中添加了一个finalize()
运算符,最后(在fillData()
中)我订阅了可以观察到,调用了真正的远程请求。
这样,如果我有许多形状像ItemsService
的服务,我就可以做到
this.loadingService.loadData(this.service1.getData()).subscribe( /* ... */ );
this.loadingService.loadData(this.service2.getData()).subscribe( /* ... */ );
this.loadingService.loadData(this.service3.getData()).subscribe( /* ... */ );
/* ... and so on */
但是,一旦我在LoadingController
中添加LoadingService
,事情就会变得很奇怪。这就是我更改服务的方式:
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;
}
}
}
现在,我得到的是加载控制器实际上显示了指示器,并且通常在远程呼叫结束后不会将其关闭。但是,有时我会得到正确的行为:指示器显示,呼叫开始,呼叫结束,指示器消失。
我对JS中基于事件的编程不是很自信,因此这可能是一个非常愚蠢的问题,但是我需要一些帮助来解决此问题。
非常感谢
马可
答案 0 :(得分:0)
我已经在几个按预期运行的应用程序中使用了以下加载程序服务。
加载程序服务
private loader;
constructor(private loaderCtrl: LoadingController) {
this.loader = null;
}
async show(message?: string) {
if (this.loader !== null) {
this.loader.dismiss();
this.loader = null;
}
this.loader = await this.loaderCtrl.create({
spinner: 'crescent',
message: message ? message : 'Please wait...',
});
return this.loader.present();
}
hide() {
if (this.loader !== null) {
this.loader.dismiss();
this.loader = null;
}
}
这是调用API的脚本-
组件ts
try {
await this.loaderSvc.show();
this.service1.getData().subscribe((res) => {
}, err => {
throw "Error calling API";
});
} catch (error) {
console.log(error);
} finally {
this.loaderSvc.hide();
}