【问题标题】:How to handle conditional observables in RxJS如何在 RxJS 中处理条件 observables
【发布时间】:2021-02-18 13:26:17
【问题描述】:

在模板中使用异步管道显示数据$。

用户可以查看所有数据,也可以在搜索框中键入并显示由 searchKey 过滤的数据。

data$的两种情况:

  • 没有 searchKey => data$ = getAllData(): Observable;
  • 用户输入searchKey => data$ = getDataBySearchKey(searchKey): Observable;

伪代码:

data$: Observable<someData[]>();
searchKeyChanged: Subject<string>();

ngOnInit() {
   this.data$ = this.dataService.getAllData();
   
   this.data$ = this.searchKeyChanged.pipe(switchMap(searchKey => this.dataService.getDataBySearchKey(searchKey)))
}

如何在 RxJS 中正确处理这个问题?

【问题讨论】:

    标签: angular rxjs


    【解决方案1】:

    您的伪代码已完成大部分工作。您所需要的只是搜索键的初始值(我使用了 null,在此实现中空字符串也可以使用)。然后你可以选择切换到什么。

    data$: Observable<someData[]>();
    searchKeyChanged: Subject<string>();
    
    ngOnInit() {
      this.data$ = searchKeyChanged.pipe(
        startWith(null),
        switchMap(searchKey => 
          searchKey != null && searchKey?.length > 0 ?
          this.dataService.getDataBySearchKey(searchKey) :
          this.dataService.getAllData()
        )
      );
    }
    

    这也是 switchMap 的理想用例,因为如果用户继续输入并且新的 searchKeys 进入,飞行中的服务调用将在中途被取消。

    顺便说一句:去抖动很好

    如果用户可以快速连续更改 searchKeys,我建议使用 debounce 来平滑用户体验。

    ngOnInit() {
      this.data$ = searchKeyChanged.pipe(
        debounceTime(500),
        startWith(null),
        switchMap(searchKey => 
          searchKey != null && searchKey?.length > 0 ?
          this.dataService.getDataBySearchKey(searchKey) :
          this.dataService.getAllData()
        )
      );
    }
    

    如果用户停止 searchKeyChanged 触发半秒,这将进行新的服务调用。这意味着 data$ 不会那么卡顿。这也是用户停止片刻然后期待结果的通常节奏。

    如果您的服务调用完成速度很慢,但可以取消(例如,它们不是转换的承诺),那么我会在服务调用之后去抖动。这需要更多的计算量,但结果应该比之前的 debounce 快 500 毫秒。

    ngOnInit() {
      this.data$ = searchKeyChanged.pipe(
        startWith(null),
        switchMap(searchKey => 
          searchKey != null && searchKey?.length > 0 ?
          this.dataService.getDataBySearchKey(searchKey) :
          this.dataService.getAllData()
        ),
        debounceTime(500)
      );
    }
    

    当然,您可以更改时间或使用 RxJS 的其他去抖动运算符之一

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-11-30
      • 2020-04-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-28
      • 1970-01-01
      相关资源
      最近更新 更多