我对Angular场景很新,我开始从一些意想不到的行为中解脱出来。
我在IntegrationsService中有以下代码
queryList(): Observable<ApiList[]> {
if(this.loadingApiList == true) {
return Observable.of(this.queryListResult);
}
this.loadingApiList = true;
return this._http
.get('samples/apiList.json').map( (response: Response) => <ApiList[]> response.json())
.do(data => {
this.queryListResult = data;
});
}
如何在路由的页面加载时停止执行此调用两次?
组件调用此方法并在导航中构建列表,另一个组件也为以下方法调用相同的服务:
getApiName(IT_ID:number) {
console.log(this.queryListResult);
let obj = this.queryListResult.find(o => o.IT_ID == IT_ID);
if(obj) {
return obj.IT_Name;
}
return false;
}
当我不使用路由时,这非常有效,但是当我使用路由时,getApiName会返回一个未定义的结果。
我也使用了resolve对象,确实解决了问题但是后来又对json文件进行了两次调用,这就是我使用的。
resolve(route: ActivatedRouteSnapshot, state:RouterStateSnapshot):Observable<any>{
return this._service.queryList() // We need this to finish first.
}
我现在真的被困住了 - 我可以使用解决方案让它工作但是两次调用.json是浪费的。
这样做的正确方法是什么?
答案 0 :(得分:1)
如何在路由的页面加载时停止执行此调用两次?
这种情况正在发生,因为您订阅了两次。 Observable是懒惰的,每次用.subscribe()
调用它时,它都会开始执行:在你的情况下,它会触发一个网络请求。将.subscribe()
视为.call()
或()
视为函数:每次调用函数时,都会执行。
考虑到这一点,您遇到的行为是预期的。有不同的方法来解决这个问题,这些方法类似但根据您的用例略有不同;即。订阅和取消订阅的确切时间。一般来说,您正在寻找的内容称为multicasting。
最简单的多播形式是使用the .shared()
operator。来自official docs;但请注意重点(我的):
返回一个新的Observable,它可以多播(共享)原始的Observable。 只要至少有一个订阅者,此Observable将被订阅并发送数据。当所有订阅者都取消订阅时,它将取消订阅源Observable。因为Observable是多播,所以它使流变热。这是
.publish().refCount()
的别名。
您可能感兴趣的是创建BehvaiorSubject
,因为它具有&#34;当前值&#34;的概念。那么你的API调用将不会返回任何内容,它只会触发请求。
这是一个概念验证:
export class Service {
public data$ = new BehaviorSubject(null);
public get() {
this.http.get(`some/data`).subscribe(data => this.data$.next(data))
}
}
null
是订阅data$
时每个订阅者将同步获得的值。你可以像这样使用它。
this.get()
this.data$.subscribe(data => /* ... */)
当然,你可以将它包装成更好的东西,甚至开始实现缓存等等。
一些有用的链接: