angular - 将 LoadingController 包裹在可观察对象周围
问题描述
我用 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
in 时PageComponent
,我从 中获取 observable ItemsService
,向其中添加一个finalize()
运算符,最后 (in fillData()
) 我订阅了 observable,调用了真正的远程请求。
这样,如果我有很多形状像 的服务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
in 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 中基于事件的编程不是很有信心,所以这可能是一个非常愚蠢的问题,但我需要一些帮助来解决这个问题。
非常感谢,
马可
解决方案
我在几个按预期工作的应用程序中使用了以下加载程序服务。
装载机服务
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();
}
推荐阅读
- javascript - 尝试安装 next.js 时我做错了什么吗?
- sql-server - SSDT2012版SSIS包可以在SQL Server 2012上执行吗?
- pyqt5 - 在pyqtgraph的ImageView中显示一个QPixmap或QImage
- html - 如何从 html 中提供的句子中生成随机句子?
- javascript - 如何通过迭代创建对象
- c# - C#中的运行长度解码
- python - Python正则表达式捕获组拆分问题
- html - CSS Overlay 使文本变暗
- python - 带有python请求的动态请求
- reactjs - 错误:操作必须是普通对象。使用自定义中间件进行异步操作。集成 React-Redux 问题