首页 > 解决方案 > RxJS 根据请求时间更改加载指示消息

问题描述

我想使用 RxJS 实现加载指示(微调器和下面的消息)。

如果数据早于 30 秒成功到达,则带有消息的加载程序将消失。

我在 Angular 项目中实现这个。下面的代码是草稿版本,它没有按预期工作,因为 api 数据等待计时器完成

  public initializeDashboard() {
    const timerMessage$ = timer(30000, 1000).pipe(take(1));
    const dashboard$: Array<any> = this.headerService.getItems();

    this.progressMessage = 'Your request is being processed...';
    merge(timerMessage$, dashboard$).pipe(
      tap((item) => {
        if (isNumber(item)) {
          this.progressMessage = 'Usually it takes less then a minute';
        }
      }),
      filter(item => isArray(item)))
      .subscribe(
        (responseData) => {
            this.progressMessage = '';
             this.responseData = responseData,
          }
      );
  }

标签: angularrxjs

解决方案


The trick here is that I'll merge two chains where the first one will only make a side-effect and update the message while the second one is the one that using take(1) can complete the chain. This is necessary because you obviously want to cancel the timer when dashboard$ emits.

I think there's another variant without ignoreElements() but that would require also takeUntil() and share() and making two separate subscriptions so this is I think the easier one.

public initializeDashboard() {
  const dashboard$: Array<any> = this.headerService.getItems();
  const timerMessage$ = timer(30 * 1000) // This will emit just once after 30s
    .pipe(
      tap(() => this.progressMessage += 'Usually it takes less then a minute'),
      ignoreElements(), // all emission will be ignored so they won't reach `take(1)` and complete the chain
    ); 

  this.progressMessage = 'Your request is being processed...';

  merge(timerMessage$, dashboard$)
    .pipe(
      take(1), // This is required so when `dashboard$` emits it will unsubscribe from `timerMessage$` automatically
    )
    .subscribe((responseData) => {
      this.progressMessage = '';
      this.responseData = responseData,
    });
}

推荐阅读