我有一个FeatureToggle守护程序,该函数调用FeatureToggle服务以获取一系列功能切换,但我一直在努力寻找如何构造可观察对象的方法,类似于我对诺言所做的操作。
后卫-
canActivate() {
if(this.toggleService.hasToggles){
return this.toggleService.isOn('my toggle');
} else {
return this.toggleService.getToggles().subscribe(() => {
return this.toggleService.isOn('my toggle')
})
}
}
服务-
@Injectable
export class ToggleService {
private _toggles: string[];
private _hasToggles: boolean;
getToggles() {
return this.http.get('...').subscribe((toggles) => {
this._toggles = toggles;
})
}
isOn(toggle) {
// return if toggle is in this._toggles;
}
}
但是,因为我已经在服务内部进行预订,所以我将返回的是订阅,而不是可观察的。我可以在getToggles
中创建对可观察对象的本地引用,然后返回该引用,但这是我应该使用的模式吗?
答案 0 :(得分:1)
您可以使用ReplaySubject
来为新订阅重复上一次发出的值,然后让getToggles()
仅调用http.get()
一次。
https://www.learnrxjs.io/subjects/replaysubject.html
@Injectable({providedIn: 'root'})
export class ToggleService {
private _toggles: ReplaySubject<string[]>;
getToggles(): ReplaySubject<string[]> {
if (!this._toggles) {
this._toggles = new ReplaySubject();
this.http.get('...').subscribe((toggles) => this._toggles.next(toggles));
}
return this._toggles;
}
isOn(toggle): Observable<boolean> {
return this.getToggles().pipe(map(toggles => toggles.includes(toggle)));
}
}
您还可以使用shareReply
运算符:
https://www.learnrxjs.io/operators/multicasting/sharereplay.html
@Injectable({providedIn: 'root'})
export class ToggleService {
private _toggles: Observable<string[]>;
getToggles(): Observable<string[]> {
if (!this._toggles) {
this._toggles = this.http.get('...').pipe(shareReplay(1));
}
return this._toggles;
}
isOn(toggle): Observable<boolean> {
return this.getToggles().pipe(map(toggles => toggles.includes(toggle)));
}
}
答案 1 :(得分:1)
使用Observables时,总是存在无法再传递Observable
的边缘。在Angular中,它们可以传递到视图模板中,并通过| async
管道进行订阅。或者,根据您的情况,返回canActivate
的返回值。因此,在您的服务中使用Observables非常方便。
在服务中,如果要缓存结果,可以使用BehaviourSubject
存储结果,然后将它们作为Observable传递给其他人。或者,您可以使用shareReplay
运算符创建一个可观察对象并重新使用它。或者,简单地,您可以将它们存储起来并使用of
中的'rxjs'
函数将它们返回。我将说明最后一个选择。
@Injectable
export class ToggleService {
private _toggles: string[];
private _hasToggles: boolean;
getToggles(refresh?: boolean) {
if (!refresh || !this.toggles) {
return this.http.get('...').pipe(
tap((toggles) => {
this._toggles = toggles;
});
);
} else {
return of(this._toggles);
}
}
您还可以从isOn
返回Observable
类型的boolean
-。这样,您就可以尽可能地传递它。
isOn(toggle): Observable<boolean> {
return this.getToggles().pipe(
map(toggles => toggles.includes(toggle))
)
}
canActivate
变得非常简单:
canActivate(): Observable<boolean> {
return this.toggleService.isOn('my toggle');
}
Angular订阅返回的observable。无需检查切换器是否已经加载-服务已经解决了这个问题。