在继续主订阅 (rxJs) 之前等待 Angular 嵌套订阅

时间:2021-03-11 18:15:14

标签: angular rxjs substring

我遇到了一个有问题的方法,我需要执行所有嵌套方法(包括 subscirbe),然后才设置 isLoading = false,但是在执行所有嵌套逻辑之前,isLoading 标志设置为 false。

你有什么想法可以告诉我吗? 我试着用示意性的方式编写代码,而不深入细节

getData() {
 isLoading = true;
 this.someSevice.getSomeData().subscribe(response => {
   ...
   getUserData(response);
   isLoading = false;
 },
  error => {
    isLoading = false;
    this.errors = error;
 });
}

getUserData(data: any) {
  ...
  this.someSevice.getUserData().subscribe(response => {
    ...
    getMetadata(response);
  });
}

getMetadata(data: any) { 
  ...
  this.someSevice.getMetadata().subscribe(response => {
    ...
  });
}

2 个答案:

答案 0 :(得分:1)

您可以使用管道通过 mergeMap 运算符按顺序执行您的请求。如果您有顺序请求,其中每个请求都需要前一个请求的响应,那么这是一种常见模式。 mergeMap 至少需要一个参数,该参数必须是返回 Observable(或 Promise)的函数。所以我也因此修改了 getUserDatagetMetadata

getData() {
  isLoading = true;
  this.someSevice.getSomeData().pipe(
    mergeMap(getUserData),
    mergeMap(getMetadata),
  )
  .subscribe(
    response => {
      isLoading = false;
    },
    error => {
      isLoading = false;
      this.errors = error;
    },
  );
}

getUserData(data: any) {
  ...
  return this.someSevice.getUserData();
}

getMetadata(data: any) { 
  ...
  return this.someSevice.getMetadata();
}

答案 1 :(得分:1)

您可以通过使用“Higher Order Mapping Operators”(mergeMapconcatMapswitchMapexhaustMap)来避免嵌套订阅。这些特殊的操作符将为您订阅一个内部可观察对象(并管理取消订阅)并传播来自它的排放。

在您的情况下,让我们使用 switchMap

  private getData() {
    this.isLoading = true;

    this.service.getSomeData().pipe(
      switchMap(data => this.service.getUserData(data.userId)),
      switchMap(user => this.service.getMetaData(user.id)),
      tap(() => this.isLoading = false)  // <--- at this point, all calls are done
    );
  }

上面的代码定义了一个以调用getSomeData()开始的流;第一个 switchMap 接收 getSomeData() 发出的值并将其映射到一个新的 observable getUserData()switchMap 将在内部订阅并将输出传递给下一个 {{ 1}},反过来做同样的事情。

switchMap 运算符被击中时,已收到来自所有 3 个先前调用的所有响应。


如果我们想要建立一个依赖于先前调用的响应的数据响应,我们需要一种方法来访问来自那些先前调用的数据。

这可以通过在 tap 中添加一个 .pipe() 来实现,基本上像这样嵌套它们:

switchMap

查看这个完全有效的 StackBlitz 示例。我相信你可以修改它以满足你的需要:-)

相关问题