【问题标题】:Using RxJS to display a loading indicator and handling timing with the merge operator使用 RxJS 显示加载指示器并使用合并运算符处理时间
【发布时间】:2020-05-29 06:04:47
【问题描述】:

我有以下最小示例来演示我所面临的问题,其中episode 是从 UI 提供的一个值,getEpisodeTitleFromApi 是一个长时间运行的可观察对象,它会发出一个字符串。

episode 为null 或大于6 的情况下,result$ 立即发出一个空字符串来处理无效或空输入。

loading$ 的意图应该很清楚了。

episode = new Subject<number>();

result$ = this.episode.pipe(
  switchMap(episode => !episode || episode > 6 ? of('') : getEpisodeTitleFromApi(episode)),
  share()
);

loading$ = merge(
  this.result$.pipe(mapTo(false)),
  this.episode.pipe(mapTo(true))
);

问题是,当episode 为 null 或大于 6 并立即发出时,loading$ 发出 false 然后发出 true。

如何连接loading$ observable 以正确的顺序发射或达到预期的结果?

【问题讨论】:

    标签: angular rxjs


    【解决方案1】:

    试试这样的:

    loading$ = combineLatest(
        this.results$,
        this.episode,
    ).pipe(
       map(([result, episode]) => !result || episode) // show loading if result is falsy or episode
    );
    

    您可能必须使用startWith 运算符来启动每个可观察对象,可能使用默认值。问题是episode 是一个主题,它总是有一个值,因此很难关闭,因为combineLatest 总是具有参数中每个可观察对象的最新值。但是这样的事情应该会让你朝着正确的方向前进。

    【讨论】:

      【解决方案2】:

      如果您不希望结果运行同步,您可以使用 observeOn 并通过 observeOn(asyncScheduler) - [RxJS - Scheduler][1] 设置宏任务的执行

      const episode = new Subject<number>();
      
      const result$ = episode.pipe(
        switchMap(episode => of('')),
        observeOn(asyncScheduler)
      );
      
      const loading$ = merge(
        result$.pipe(mapTo(false)),
        episode.pipe(mapTo(true))
      );
      
      loading$.subscribe(console.error);
      
      episode.next(1);
      
      Output: true, false
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-06-17
        • 1970-01-01
        • 1970-01-01
        • 2021-10-26
        相关资源
        最近更新 更多