RxJS BehaviorSubject来自http呼叫的兑现请求

时间:2019-04-01 09:36:50

标签: angular rxjs rxjs6

我很难找到新的解决方案来兑现对BehaviorSubject的http请求。我只想有一种兑现和获取价值的方法。下面的示例:

@Injectable({
  providedIn: 'root'
})
export class DataStoreService {

  private readonly initialState: DataState = {
    data: string,
    loaded: false
  };

  private data$: BehaviorSubject<DataState> = new BehaviorSubject<DataState>(this.initialState);

  constructor(private dataService: DataService) { }

  getData$(id: string): Observable<string> {
    return this.data$.asObservable()
      .pipe(
        switchMap((state: DataState) => {
          if (!state.loaded) {
            this.dataService.getData$(id);
          } else {
            return of(state.data);
          }
        }),
        withLatestFrom(this.data$.asObservable()),
        map(([data, state]) => {
          if (!state.loaded) {
            this.data$.next({
              loaded: true,
              data
            });
          }
          return data;
        })
      );
  }
}

我尚未测试(服务无法正常工作),但目前看来还可以。有人知道有什么更好的解决方案,可以在rxjs中使用较少的管道和条件(如果/其他)吗?

3 个答案:

答案 0 :(得分:1)

BehaviourSubject在“ .value”中确实有一个非常简单的值访问器。

因此您的代码可能类似于

getData$(id: String): Observable<string> {
  const dataValue = this.data$.value;
  if (dataValue.loaded === true) {
    return of(dataValue.data);
  } else {
    return this.dataService.getData$(id).pipe( map( (result: string) => { this.data$.next({ loaded: true, data: result}; return of(result); );
  }
}

希望这会有所帮助。

答案 1 :(得分:1)

我的看法有所不同,实际上并没有使用行为主题,只是一个变量。如果您愿意这样做,则可以考虑:

data;

getData$(id: string): Observable<string> {
  if (data) {
    return of(data)
  } else {
    return this.dataService.getData$(id).pipe(
      tap(dat => this.data = dat)
    )
  }
}

答案 2 :(得分:1)

您可以使用运算符BehaviorSubject代替shareReplay,该运算符在内部使用ReplaySubject并向将来的订户重放n个最新值。

private data$: Observable<string>;

getData$(id: string): Observable<string> {
  if (!this.data$) {
    this.data$ = this.dataService.getData$(id).pipe(shareReplay(1));
  } 
  return this.data$;
}

getData$的第一个订阅将称为this.dataService.getData$。所有以后的订阅都将从data$重播的第一个呼叫中获取数据。