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

如何在RxJS中消除订阅与错误回调重复代码以封装加载状态

使用场景

我有一个由RxJS Observable启动的加载操作,希望在操作结束时结束/封装该加载状态。Observable要么返回错误,要么返回新数据。
结束既指Observable返回错误,也指它触发新值。
补充说明:在下面的变体中,我还有另一个Observable来触发整个加载流程。

最小可复现示例

可以通过复制代码简单实现,但存在代码重复:

const {
  from,
  concat,
  throwError
} = rxjs;


concat(
  from([1, 2, 3]),
  throwError("fail")
).subscribe((x) => {
    console.log("loading end", x);
  },
  (x) => {
    console.log("loading end", x);
  }
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/7.5.7/rxjs.umd.min.js"></script>

我本质上是想找一个操作符来消除上述示例中的代码重复。

显示加载状态

显示加载状态自然要在Observable执行前,比如用tap操作符:

const {
  from,
  concat,
  throwError,
  pipe,
  tap
} = rxjs;


concat(
  from([1, 2, 3]),
  throwError("fail")
).pipe(
   tap(() => console.log("show loading"))
).subscribe((x) => {
    console.log("loading end", x);
  },
  (x) => {
    console.log("loading end", x);
  }
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/7.5.7/rxjs.umd.min.js"></script>

不过tap触发的显示加载操作不会在错误时执行。

实际场景示例

但在我的实际实现中不会出现这种情况,因为我合并了两个Observable,且有一个触发Observable来启动整个流程:

const {
  from,
  concat,
  throwError,
  pipe,
  tap,
  switchMap,
  Subject
} = rxjs;

// this is the trigger to load stuff (in Angular triggered from the outside component e.g.)
loadData$ = new Subject();

loadData$ //< <- this is irrelevant now and just the trigger
  .pipe(
    tap(() => console.log("show loading")), // <-- show loading when/before data loading starts
    switchMap(() => {
      return concat(
        from([4, 5, 6]),
        throwError("fail")
      )
    })
  ).subscribe((x) => { // <-- end loading when/after data loading ends or fails
      console.log("loading end", x);
    },
    (x) => {
      console.log("loading end", x);
    }
  )


loadData$.next(); // just trigger for testing here
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/7.5.7/rxjs.umd.min.js"></script>

尝试过的方法

  • 我试过finalize操作符,但它只在完成时触发(无论是否出错),因此不适用。
  • 我认为complete回调也会有同样的效果。

发现的问题

在撰写本文时,我意识到如果Observable出错,后续无法发射新值。(实际情况是否如此?)

const {
  from,
  concat,
  throwError,
  of
} = rxjs;

concat(
  from([1, 2, 3]),
  throwError("fail"),
  of ("another value") // <-- is not triggered
).subscribe((x) => {
    console.log("loading end", x);
  },
  (x) => {
    console.log("loading end", x);
  }
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/7.5.7/rxjs.umd.min.js"></script>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 13:30:41