首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >RxJS (和Angular):尝试缓存一次性HTTP请求仍然会导致多个请求

RxJS (和Angular):尝试缓存一次性HTTP请求仍然会导致多个请求
EN

Stack Overflow用户
提问于 2017-10-05 10:32:46
回答 2查看 792关注 0票数 0

我还在适应RxJS的过程中,所以这可能是一个简单的问题。

目前,我正在尝试懒惰地对某些数据发出XHR请求,这些数据只需要获取一次,然后在页面打开时无限期地缓存。我认为,通过尝试利用从Angular的HTTP客户端发出的值的AsyncSubject,我走上了正确的道路。到目前为止,我得到的基本上是这样的:

代码语言:javascript
复制
@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$之前请求是不会发出的,并且当我有超过1个观察者时,.share()应该防止发出额外的请求。

但是,如果我取消订阅它,并且extraInfo$变冷(因为有0个订阅者),再次订阅它会导致再次发出额外的请求。

现在,我很想覆盖AsyncSubject上的._subscribe()属性,这样我就可以在请求获得第一个观察者时运行它,但这感觉有点太黑客了。

EN

回答 2

Stack Overflow用户

发布于 2017-10-06 05:24:56

如果您想要执行一个请求,然后在任何后续订阅中缓存此请求的结果,则可以更轻松地完成此操作:

代码语言:javascript
复制
@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就是你需要的。

票数 1
EN

Stack Overflow用户

发布于 2017-10-06 05:15:34

我最终想出了一些东西,下面是我所需要的:

代码语言:javascript
复制
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,因为如果需要,我可以扩展以设置刷新数据的间隔。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46576998

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档