【问题标题】:Manage API data reponse with rxjs and manage application state - Angular 10使用 rxjs 管理 API 数据响应并管理应用程序状态 - Angular 10
【发布时间】:2020-12-02 02:02:52
【问题描述】:

我正在尝试了解从 api 存储(和更新)数据并在兄弟组件之间共享该数据的最佳方式。这是我尝试过的。

保存可观察对象

export class MyExampleService {
   private data: Observable<any>;

   constructor(private readonly http: HttpClient) { }

   getData(): Observable<string[]> {
       //if we already got the data, just return that
       if (data) {
           return data;
       }

       //if not, get the data
       return this.http.get<string[]>('http://my-api.com/get-stuff')
           .pipe(tap((returnedData: string[]) => {
               //save the returned data so we can re-use it later without making more HTTP calls
               this.data= returnedData;
           }));
   }
}

但是这种方法并不能真正满足我的需求,因为它不使用任何主题,并且我想在数据更改时告诉我的其他组件。

使用主题

export class MyExampleService {
   private dataSbj: BehaviorSubject<any> = new BehaviorSubject(null);
   
   readonly data$ = this.dataSbj.asObservable();

   constructor(private readonly http: HttpClient) { }

   getData(): Observable<string[]> {

       if (dataSbj.getValue() === null) {
           return this.http.get<string[]>('http://my-api.com/get-stuff')
           .pipe(tap((returnedData: string[]) => {
               //save the returned data so we can re-use it later without making more HTTP calls
               this.dataSbj.next(returnedData);
           }));
       }          
   }
}

然后我只需在第一次订阅 getData 并订阅所有其他组件中的 data$ observable。 (在这种情况下,我有一个父组件和多个子路由,所以我会在父组件中订阅 getData() 并在所有子路由中订阅 data$。

最后一种方法可行,但我宁愿使用相同的函数来检索相同的数据,而不是通过订阅不同的 observables。

这被认为是一种好方法还是我可以做的更好?

【问题讨论】:

  • 将数据存储在 cookie 中,在您的应用中使用身份验证和授权来限制数据
  • 这听起来不对。我的意思是你可以做到,但我认为这不是最好的方法。在我的情况下,我更喜欢在内存中存储

标签: angular rxjs angular-services


【解决方案1】:

NGRX store 状态管理是在数据可用时从存储读取的方法,而不是进行不必要的网络调用。

它负责通过调度相关操作来创建、更新和删除存储中的记录。

这里是 github 上的完整源代码 DEMO,了解如何使用 ngrx 商店。

我强烈建议使用 ngrx 商店,它有一些很酷的功能,可以避免不必要的网络调用,从而导致您的应用程序加速。

【讨论】:

  • 我读到这是应用程序变大时的最佳方法,但我的情况并非如此。我还应该考虑这个选项吗?
  • 1) 将来您的应用程序也可能变得更大,从一开始,如果您遵循最佳方法,您的应用程序在变得更大时就不会变得混乱。 2)我不认为它最适合更大的应用程序这是管理数据的最佳方法,我们应该在应用程序的乞求时考虑
  • @KamranKhatti 对于简单的应用程序,使用您自己的简单 BehaviorSubject 数据存储比使用状态管理系统过于复杂更有意义,但这显然是基于意见的。
  • @PoulKruijt 我同意,但我的观点是,今天你的应用程序很简单,明天它可能会发展并变得更大,在这种情况下你不需要重构这些类型的代码实现。
  • @KamranKhatti 但如果你确定它不会变​​大,你就会被英国媒体报道所困:) 特别是 ngrx,它非常冗长,需要大量样板
【解决方案2】:

如果您的getData() 方法没有参数,您应该能够通过使用shareReplay() 运算符来执行以下操作。它只会在第一个消费者订阅它时调用 API,并将最后一次发出返回给任何顺序调用。这还包括一种更新数据的方法:

@Injectable({
  providedIn: 'root'
})
export class ExampleService {
  private updateData$ = new BehaviorSubject<void>(void 0); 

  readonly data$ = this.updateData$.pipe(
    switchMap(() => this.http.get('https://reqres.in/api/users')),
    shareReplay(1)
  );

  constructor(private readonly http: HttpClient) {}
   
  refresh(): void {
    this.updateData$.next();
  }
}
export class ExampleComponent {
  data$: Observable<any>;

  constructor(private example: ExampleService) {}

  getApi(): void {
    this.data$ = this.example.data$;
  }

  refresh(): void {
    this.example.refresh();
  }
}

working example查看控制台日志

【讨论】:

  • 如果对 API 进行更新/变异查询,我将如何强制更新数据?
  • 感谢您的更新。还有一件事。如果数据得到更新并且我想与组件共享这些新数据而无需刷新页面或新订阅 getData() 我该怎么做? (我想我需要一个我在第二种方法中描述的主题)
  • @MarcoRipamonti 在这种情况下,您不应该使用函数。我给你看
  • 我很乐意等待您的回复。谢谢。
猜你喜欢
  • 2023-01-23
  • 2018-08-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-26
  • 2018-12-19
  • 2021-06-20
相关资源
最近更新 更多