【问题标题】:Angular - Multiple subscribe sequence doesn´t workAngular - 多个订阅序列不起作用
【发布时间】:2019-12-04 12:12:56
【问题描述】:

在角度我想创建一个多订阅序列。当第一次订阅完成后,再进行下一次订阅。与此类似。

this.globalCtrl.getSon().subscribe(
                  response => {
                    this.son= response;
                  },
                  error => {
                    console.log(error);
                  },
                  () => {
                   //DOESN´T ENTER IN THIS SUBSCRIBE
                    this.dashboardCtrl.getMarkers(this.son).subscribe(

                      response => {
                        this.markers = response["body"]["data"];
                        if (this.markers.length == 0) {
                          this.toast.fire({
                            type: "error",
                            title: "No hay datos geográficos del grupo seleccionado"
                          });
                        }
                        this.timezone = response["body"]["timezone"];
                      },
                      error => {
                        console.log(error);
                      }
                    );

问题:没有进入第二次订阅并且“响应”有数据。 ¿ 有谁知道我该怎么做?

更新

如果我将第二个订阅放在这样的响应中

  this.globalCtrl.getSon().subscribe(
                      response => {
                        this.son= response;
                        this.dashboardCtrl.getMarkers(this.son).subscribe(

                          response => {
                            this.markers = response["body"]["data"];
                            if (this.markers.length == 0) {
                              this.toast.fire({
                                type: "error",
                                title: "No hay datos geográficos del grupo seleccionado"
                              });
                            }
                            this.timezone = response["body"]["timezone"];
                          },
                          error => {
                            console.log(error);
                          }
                        );

有效,但视图不显示数据。当我刷新视图数据加载正确,但在第一次加载不加载数据。

更新 2:使用开关图

  this.globalCtrl.getfather().pipe(
      switchMap(son=> this.dashboardCtrl.getMarkers(son.toString()).subscribe( /ERROR
        response => {
          this.markers = response["body"]["data"];
          if (this.markers.length == 0) {
            this.toast.fire({
              type: "error",
              title: "No hay datos geográficos del grupo seleccionado"
            });
          }
          this.timezone = response["body"]["timezone"];
        },
        error => {
          console.log(error);
        }
      )
    );

属性订阅在 OperatorFunction 中不存在

可能是可观察到的导致错误

 getFather(): Observable<any> {
    return this.grupo.asObservable();
  }

【问题讨论】:

标签: angular rxjs


【解决方案1】:

建议您不要将一个订阅嵌套在另一个订阅中。它使管理变得困难,并且几乎不可能正确退订。请改用switchMap。

这是我的一个示例应用程序中的一个示例:

  todosForUser$ = this.http.get<User>(`${this.userUrl}/${this.userName}`)
    .pipe(
      switchMap(user =>
        this.http.get<ToDo[]>(`${this.todoUrl}?userId=${user.id}`)
      )
    );

你可以在这里看到这段代码:

https://stackblitz.com/edit/angular-todos-deborahk

使用您的代码,它会是这样的(未检查语法):

import { switchMap } from 'rxjs/operators';

this.globalCtrl.getSon()
 .pipe(
    switchMap(son => this.dashboardCtrl.getMarkers(son))
 ).subscribe(...);

更新:简化的初始示例,最初演示了如何处理多个相关的数据集。

【讨论】:

  • 一定要如上图那样导入,一定要拼写switchMap(小's')
  • 这应该是公认的答案。其他答案使用嵌套的subscribe(),这不是 Angular/RxJS 的做事方式
  • 您的括号好像不太对:switchMap(son=&gt; this.dashboardCtrl.getMarkers(son))).subscribe 您需要在订阅前关闭pipe()。见上文,我有 3 个右括号。
  • switchMap 会起作用,但对于他的情况,mergeMap 会更合适。
  • 我也一直在使用mergeMap...但是我在任何讨论嵌套订阅的地方发现的每个示例都使用switchMap。如果我真的想切换(比如获取用户按钮点击数据时),我通常只使用 switchMap。
【解决方案2】:

您必须将第二个订阅移到第一个订阅中:

this.globalCtrl.getSon().subscribe(
              response => {
                this.son= response;
                  this.dashboardCtrl.getMarkers(this.son).subscribe(
                  response => {
                    this.markers = response["body"]["data"];
                    if (this.markers.length == 0) {
                      this.toast.fire({
                        type: "error",
                        title: "No hay datos geográficos del grupo seleccionado"
                      });
                    }
                    this.timezone = response["body"]["timezone"];
                  },
                  error => {
                    console.log(error);
                  }
              },
              error => {
                console.log(error);
              } 
                );

【讨论】:

    【解决方案3】:

    您的第二次订阅放错了位置。它应该在第一次订阅的响应中

    this.globalCtrl.getSon().subscribe(
                      response => {
                        this.son= response;
                        // ADD THE OTHER SUBSCRIBE HERE
                      },
                      error => {
                        console.log(error);
                      }
    

    observable 回调有 3 种类型 - next、error、complete

    您将第二个订阅放入 complete 回调中,这就是它从未被调用的原因(您的第一个 observable 从未完成)。

    阅读更多关于 Observables 的信息here

    【讨论】:

      【解决方案4】:

      在订阅中拥有订阅称为扁平化

      作为对@DeborahK 的回应,使用switchMap 会起作用,但这是对它的滥用。 switchMap 如果您的第一个可观察对象在已经订阅的情况下可以更改,那将是一种方法。更好的方法是使用mergeMap,也(以前)称为flatMap

      mergeMap - 当你有一个 Observable 的结果是另一个 Observable 时使用它

      switchMap - 当你有一个可以改变的 Observable 并且它的结果是另一个 Observable 时使用它

      如果你的第一个 Observable 发出了一些东西,mergeMap 不会丢弃前一个 Observable,因此你的内部订阅仍然会订阅前一个。在 switchMap 中,它会丢弃之前的 Observable,而内部订阅将订阅内部的。

      解决办法:

      import { mergeMap } from 'rxjs/internal/operators/mergeMap';
      .......
      .......
      
      this.globalCtrl.getSon().pipe(
        mergeMap((response) => {
          this.son = response;
          return this.dashboardCtrl.getMarkers(this.son)
        })
      ).subscribe((res) => {
        this.markers = response["body"]["data"];
      });
      

      【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-22
      • 2019-06-28
      • 1970-01-01
      • 2020-12-13
      • 2018-08-14
      相关资源
      最近更新 更多