【问题标题】:Combine arrays from observables without waiting for all to complete组合来自 observables 的数组,而无需等待全部完成
【发布时间】:2022-01-04 14:20:54
【问题描述】:

在我的应用程序中,我以一定的时间间隔从远程服务器检索数据。数据被格式化为对象数组,并通过角度异步管道显示在 HTML 模板中。
我正在使用shareReplay() 提供缓存功能:

  private refresherToggleSales$: Subject<void>;
  private displayLastSales$: Observable<Sale[]>;

  public InjectSale$: Subject<Sale[]>;
  
  [...]

   get LastSales() : Observable<Sale[]> {
    if (!this.displayLastSales$) {
      const rTimer$ = timer(0, DefaultRefresh);

      this.displayLastSales$ = rTimer$.pipe(
        switchMap(_ => this.getLastSales()),
        shareReplay(this.CACHE_SIZE),
        takeUntil(this.refresherToggleSales$)
      );
    }

    return merge(this.displayLastSales$, this.InjectSale$);
  }

  private getLastSales() : Observable<Sale[]> {
    // get data from server
  }

每当在应用程序中手动输入销售时,我希望它立即显示,而不必等待它来自服务器。

但是,如果我使用 1 元素数组调用 InjectLastSale$.next(),它将完全替换所有以前的数据。
如何合并这两个流(无需一个等待另一个完成)?

谢谢

【问题讨论】:

  • 你可以使用 combineLatest Operater combineLatest(this.displayLastSales$, this.InjectSale$).subscribe( (displayLastSales, InjectSale) => { console.log(displayLastSales, InjectSale ) })发出后,您将立即看到它,而无需等待其他可观察对象发出数据。

标签: angular typescript rxjs observable


【解决方案1】:

你已经接近了!只需更改您放置 merge 的位置即可。

get LastSales() : Observable<Sale[]> {
    
  if (!this.displayLastSales$) {
    this.displayLastSales$ = timer(0, DefaultRefresh).pipe(
      switchMap(_ => this.getLastSales().pipe(
        mergeWith(this.InjectSale$),
        scan((acc, vals) => [...vals, ...acc], <Sale[]>[])
      )),
      shareReplay(this.CACHE_SIZE),
      takeUntil(this.refresherToggleSales$)
    );
  }

  return this.displayLastSales$;
}

【讨论】:

    【解决方案2】:

    你可以使用 combineLatest 操作符

    combineLatest(this.displayLastSales$, this.InjectSale$).subscribe(
    (displayLastSales, InjectSale) => {
            console.log(displayLastSales, InjectSale )
          })
    

    现在,无论何时发出数据,您都会立即看到它,而无需等待其他 observable 发出数据。

    【讨论】:

    • RXJS 文档状态 请注意,在每个 observable 发出至少一个值之前, combineLatest 不会发出初始值 所以在应用启动时我需要手动触发 InjectLastSale$.next() 或否则什么都不会显示
    猜你喜欢
    • 2017-05-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-22
    • 2018-12-01
    • 1970-01-01
    相关资源
    最近更新 更多