RxJS(和Angular):尝试缓存一次性HTTP请求仍然会导致多个请求
问题描述:
我仍然对RxJS感到满意,所以这可能是一个简单的问题。RxJS(和Angular):尝试缓存一次性HTTP请求仍然会导致多个请求
目前我正试图懒惰地为某些数据做一个XHR请求,我只需要一次获取一次数据,然后在页面打开时无限期地缓存,并且我想通过试图利用一个AsyncSubject
与从Angular的HTTP客户端发出的价值。我至今基本上是这样的:
@Injectable()
class AuthService {
user$ = new BehaviorSubject(null);
// do .switchMap() so we reset when the auth'ed user changes
extraInfo$ = this.user$.switchMap(() => {
return this.http.get('/api/account').share();
});
constructor(http: HttpClient) { }
...
}
这几乎工程,因为该请求不发,直到事情订阅extraInfo$
和.share()
应该防止产生额外的请求时我已经在这1个多观察。
但是,如果我取消订阅它并且extraInfo$
变冷(因为有0个订阅者),再次订阅它会导致再次发出额外的请求。
现在我很想重写AsyncSubject
上的._subscribe()
属性,这样我就可以在请求得到它的第一个观察者时运行请求,但这有点太过分了。
答
我发生什么事了最后,以下作品我需要什么:
const lastFetchedInfo = new WeakMap();
@Injectable()
class AuthService {
user$ = new BehaviorSubject(null);
// do .switchMap() so we reset when the auth'ed user changes
extraInfo$ = this.user$.switchMap(user => !user ? Observable.empty() : new Observable((observer) => {
if (!lastFetchedInfo.has(user)) {
const subject = new BehaviorSubject(null);
lastFetchedInfo.set(user, subject.filter(o => o !== null));
this.http.get('/api/account').subscribe(info => subject.next(info));
}
const subscription = lastFetchedInfo.get(user);
return() => subscription.unsubscribe();
}));
constructor(http: HttpClient) { }
...
}
我决定用一个BehaviorSubject
,而不是AsyncSubject
因为我可以扩展到从这里如果刷新数据设置的时间间隔我需要。
答
如果要执行一个请求,然后将结果缓存这个在任何后续的订阅,你可以这样做容易得多:
@Injectable()
class AuthService {
user$ = new BehaviorSubject(null);
extraInfo$ = this.user$.switchMap(() => {
return this.http.get('/api/account').shareReplay(1);
});
constructor(http: HttpClient) { }
...
}
使用shareReplay(1)
正在修复您有相关的问题share
运营商。他们都是多播运营商,但具有不同的属性。您希望操作员具有可重复性而不可重试(请参阅我撰写的关于此主题的文章,以帮助您了解我的意思http://blog.kwintenp.com/multicasting-operators-in-rxjs/)。
请记住,如果您想无限期地缓存某个可观察结果,则需要shareReplay
。
我看到'BehaviorSubject' –