使用rxjs管理API数据响应并管理应用程序状态-Angular 10

问题描述

我试图了解从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 $。 (在这种情况下,我有一个父组件和更多子路由,因此我将在父组件中订阅getData()并在所有子路由中订阅data $。)

这最后一种方法可行,但我宁愿使用相同的函数来检索相同的数据,而不是订阅不同的可观察对象。

这被认为是一种好方法吗?或者我能做些更好的事情吗?

解决方法

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

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

这是github上有关如何使用ngrx存储的完整源代码DEMO

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

,

如果您的getData()方法没有参数,则应该能够利用shareReplay()运算符执行以下操作。仅当第一个使用者订阅该API时,它才会调用该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检查控制台日志