简体   繁体   English

在订阅 Observable 之前在主题中存储 API 数据 - Angular 10

[英]Store API data in subject before subscribing to Observable - Angular 10

I'm trying to store data returned from an API inside a behaviour subject with the next method and I'd like to do this before subscribing to the observable.我正在尝试使用 next 方法将从 API 返回的数据存储在行为主题中,我想在订阅可观察对象之前执行此操作。

Let's say I have service which has this function to retrieve some data from an API:假设我的服务有这个 function 从 API 检索一些数据:

getData(): Observable<Data> {
    return this.http.get(APIURL);
}

Now before subscribing to getData() I'd like to save what has been returned from the API in a subject.现在,在订阅 getData() 之前,我想将从 API 返回的内容保存在一个主题中。 I managed to achieve this with the tap() operator, but by reading the documentation, tap should be used for side effects and in this case it doesn't look like one.我设法用 tap() 运算符实现了这一点,但通过阅读文档,tap 应该用于副作用,在这种情况下它看起来不像一个。 So what I did was something like this:所以我所做的是这样的:

getData(): Observable<Data> {
        return this.http.get(APIURL)
               .pipe(tap(data => this.subject.next(data));
}

I'm doing this so I can have some sort of cache so that I don't have to call the API again and do some manipulation on that data when it gets updated.我这样做是为了拥有某种缓存,这样我就不必再次调用 API 并在数据更新时对其进行一些操作。 For instance let's say I add an element to that data with an update query, now I can update the previous data stored in the subject so everything is up to date.例如,假设我使用更新查询向该数据添加了一个元素,现在我可以更新主题中存储的先前数据,以便一切都是最新的。 Only by refreshing the page I would call the API again.只有刷新页面,我才会再次拨打 API。

What is unclear to me is the use of the tap operator, is it fine to use it like this or are there better alternatives for what I'm trying to do?我不清楚的是水龙头运算符的使用,像这样使用它是否可以,或者对于我正在尝试做的事情有更好的选择吗?

If I understand right, you can just check, that you have some data in Subject如果我理解正确,你可以检查一下,你在 Subject 中有一些数据

subject = new BehaviorSubject<any>(null);

getData(): Observable<Data> {
   if (subject.getValue()) {
      return of(subject.getValue());
   }
   return this.http.get(APIURL)
        .pipe(tap(data => this.subject.next(data));
}

Here is a CodeSandbox that shows one way to manage your cache request flows in the case where you don't use a state management library.这是一个CodeSandbox ,它显示了一种在您不使用 state 管理库的情况下管理缓存请求流的方法。

The essence of the demo is the following demo的本质如下

 interface IArticle { title: string; content: string; } @Injectable({ providedIn: "root" }) export class HttpDemoCache { // You need a variable where to store the data cachedArticleResponse$: BehaviorSubject<IArticle[]> = new BehaviorSubject([]); ... loadArticles(someQuery) { // You need a method that fetches the data from the BE this.httpClient.get(...).subscribe((x) => { this.cachedArticleResponse$.next(x); }); } updateArticles(newArticle: IArticle) { // You need a update method to send the new enttity to the back-end + update your cached version this.http.post(...., {newArticle}).pipe( switchMap(response => this.cachedArticleResponse$.pipe( take(1), tap(cachedArtilces => this.cachedArticleResponse$.next([...cachedArticles, newArticle])) ) ) ).subscribe() }); } }

Pretty much with this solution you are creating your own state-management solution which responsibility will be to take care of all cahce/fetch/upload/delete logic.通过此解决方案,您几乎可以创建自己的状态管理解决方案,其职责是处理所有 cahce/fetch/upload/delete 逻辑。

The benefit of this solution is that you have way more control over what is happening than when you are fetching the data directly in the components.该解决方案的好处是,与直接在组件中获取数据相比,您可以更好地控制正在发生的事情。

** Side-note: keep in mind that this is a verry brief example of a concept, not a detailed solution. ** 旁注:请记住,这是一个非常简短的概念示例,而不是详细的解决方案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM