我有一个Angular应用程序,其中包含使用HTTP(EnvironmentConfigService
)读取运行时配置的服务,以及另一个使用该服务中的数据来计算各种服务的URL的服务(UrlManagerService
)并将它们提供给应用程序的其余部分。
我希望这种行为的方式是:UrlManagerService
在应用启动时读取配置,并提供调用者用于通过observable获取计算URL的方法。如果HTTP请求仍在进行中,则observable在请求完成时发出;如果请求已经完成,则observable会立即发出内存中的数据。
目前代码如下:
import { Injectable } from '@angular/core';
import { EnvironmentConfigService } from './environment-config.service';
import { Observable } from 'rxjs/Observable';
@Injectable()
export class UrlManagerService {
// it has public properties for all of the URLs
private configLoaded: Observable<UrlManagerService>;
constructor(private configService: EnvironmentConfigService) {
this.configLoaded = this.configService
.read()
.map(config => {
// compute URLs and assign to properties
return this;
});
this.configLoaded.subscribe(() => {
this.configLoaded = Observable.of(this)
});
}
public getInitialized(): Observable<UrlManagerService> {
return this.configLoaded;
}
}
getInitialized
方法返回HTTP请求的observable(由EnvironmentConfigService.read
返回),当它正在进行时;一旦读取了数据,它就会变为使用Observable.of
创建的静态observable。
我主要担心的是:
subscribe
调用中重新执行HTTP请求)。 答案 0 :(得分:2)
您可以使用shareReplay(1)
通过ReplaySubject多播observable。与publishReplay(1).refCount()
不同,即使在某些时候没有订阅者,这也会保留缓存。它仍然可以在错误上重试,这使得它非常适合。
return this.configService.read()
.shareReplay(1);
但是,你需要rxjs 5.5.0或更高版本,因为它有一个重要的错误修正。
答案 1 :(得分:1)
1)您可以继续使用http observable。做一些像:
this.configLoaded = this.configService
.read()
.map(config => {
// compute URLs and assign to properties
return this;
})
.publishReplay(1)
.refCount();
.publishReplay(1) - &gt;缓存最近的值。
.refCount() - &gt;只要有订阅者,就会保持可观察性。
2)一旦http请求完成,它就会自行完成,因此无需取消订阅。
答案 2 :(得分:1)
您可以使用AsyncSubject
,请参阅What's the point of AsyncSubject in RXJS
@Injectable()
export class UrlManagerService {
private configLoaded = new AsyncSubject<UrlManagerService>();
constructor(private configService: EnvironmentConfigService) {
this.configService
.read()
.map(config => {
// compute URLs and assign to properties
return this;
})
.subscribe(this.configLoaded) // pass the result and the 'complete' notification
}
public getInitialized(): Observable<UrlManagerService> {
return this.configLoaded.asObservable();
}
}