You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修正firstLoad$与paged$两个Observable的加载顺序问题?

修正Observable执行顺序问题

你当前代码的问题在于使用了mergeMap,它会并行订阅firstLoad$和paged$两个Observable,哪个先完成就先触发后续的scan逻辑,完全不保证顺序。这就是paged$加载更快时执行顺序不符合预期的原因。

方案1:用concatMap替换mergeMap

concatMap会严格按照Observable的传入顺序串行处理——必须等前一个Observable完成并处理完毕,才会订阅下一个。修改后的代码如下:

of(firstLoad$, paged$)
  .pipe(
    concatMap((curr: Observable<ISubject[]>) => curr),
    scan((acc: ISubject[], curr: ISubject[]) => {
      if (acc.length > 0) {
        return [...curr];
      } else {
        return [...acc, ...curr];
      }
    }, [])
  )
  .subscribe((result) => {
    if (result.length === 0) {
      setTimeout(() => {
        this.loading = false;
      }, 300);
    } else {
      this.subjects = this.subjects.concat(result);
      this.errorStatus = Array(this.subjects.length);
      this.subjectsSubject$.next(this.subjects);
      this.loading = false;
    }
  });

方案2:直接使用concat操作符(更简洁)

concat操作符本身就是用来按顺序拼接Observable的,不需要额外用of包裹,代码更直观:

concat(firstLoad$, paged$)
  .pipe(
    scan((acc: ISubject[], curr: ISubject[]) => {
      if (acc.length > 0) {
        return [...curr];
      } else {
        return [...acc, ...curr];
      }
    }, [])
  )
  .subscribe((result) => {
    if (result.length === 0) {
      setTimeout(() => {
        this.loading = false;
      }, 300);
    } else {
      this.subjects = this.subjects.concat(result);
      this.errorStatus = Array(this.subjects.length);
      this.subjectsSubject$.next(this.subjects);
      this.loading = false;
    }
  });

原理说明

concat/concatMap的核心逻辑是串行订阅:先订阅firstLoad$,等它完成(发出所有数据并触发complete)后,才会订阅paged$。这样不管paged$的加载速度有多快,都会严格等待firstLoad$处理完成后再执行,完全保证你需要的顺序。

内容的提问来源于stack exchange,提问作者Joelad

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 10:40:19