2017-09-24 62 views
0

我对角度场景相当陌生,我开始将我的头发从某些意外行为中解脱出来。角度 - 服务中的观察对象

我在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返回未定义的结果。

我也使用了解析对象,这确实解决了问题,但随后两个调用正在对json文件进行,这就是我使用的。

resolve(route: ActivatedRouteSnapshot, state:RouterStateSnapshot):Observable<any>{ 
    return this._service.queryList() // We need this to finish first. 
    } 

我现在真的卡住 - 我能得到它的工作使用的决心,但有两次调用以.json这是一种浪费。

这样做的正确方法是什么?

+0

设定了标志,并不一定意味着该操作完成,并且查询结果列表中已被分配。一种实现这一点的方法是将数据暴露在基于主题的观察值上并触发一次提取,参见例如。 https://blog.jonrshar.pe/2017/Apr/09/async-angular-data.html,其中展示了我们如何使用这种模式。 – jonrsharpe

回答

1

如何阻止此次调用在路由页面加载时执行两次?

发生这种情况是因为您订阅了两次。可观察对象是懒惰的,每次你调用.subscribe()时,它都会开始执行:在你的情况下,它会触发一个网络请求。将.subscribe()想象为.call()或简单地()函数:每次调用一个函数时,它都会执行。

考虑到这一点,预计会遇到您遇到的问题。有不同的方法可以解决这个问题,根据您的使用情况,这些方法相似但略有不同;即。订阅和取消订阅的确切时间。一般来说,你要找的是multicasting

多播的最简单形式是使用the .shared() operator。来自official docs;但要注意的重点(我的):

返回多播(共享)原始Observable的新Observable。 只要有至少一个订户这个Observable将被订阅并发布数据。当所有订阅者取消订阅时,它将取消订阅源Observable。由于Observable正在多播,因此会使流变为热点。这是.publish().refCount()的别名。

你可能会感兴趣什么是创造一个BehvaiorSubject,因为它具有“当前值”的概念。然后你的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 => /* ... */) 

当然,你可以用这个弄成更好,甚至开始执行之类的东西缓存等


一些有用的链接:

+0

谢谢你的详细解答。由于每个调用get()的组件都不会使用BehaviorSubject导致两个请求发生同样的问题? – Colin

+0

没错,这就是为什么我说,我在这里给出的设置仅仅是一个起点,了解'BehaviorSubject'。这个想法是你应该处理该端点可以通过定制逻辑来调用的频率。您不希望_never_再次调用它,因为数据可能会过时。从RxJS的角度来看,众所周知,你所做的这两个呼叫可能是不同的结果。这取决于你如何缓存响应并确定响应是否有效。 –

+0

只是要清楚,如果我对服务的ngOnInit称为get()方法,以确保数据存在。所有的组件订购了之前和之后这个get()会收到更新的数据副本,当它是可用的使用订阅? – Colin