【问题标题】:How do I refactor nested subscribes with switchmap or other rxjs options when working with Firestore Observables?使用 Firestore Observables 时,如何使用 switchmap 或其他 rxjs 选项重构嵌套订阅?
【发布时间】:2020-11-08 20:31:45
【问题描述】:

我是 Angular 新手,在我了解发生了什么之前要爬一座小山,使用 Firestore 中的 observables 让我很困惑。我需要一个服务调用中的 ID 字段来从以下两个服务调用中获取数据,同时避免可怕的未定义。我们如何做到这一点?

this.myMatch = this.route.snapshot.paramMap.get("createdMatchIdKey");

this.golfDataService.GetSelectedMatch(this.myMatch)
  .subscribe(result => {
    this.match = result;
    this.setupTable(this.match.matchCourseId);
    this.golfDataService.GetSelectedGolfCourse(this.match.matchCourseId)
      .subscribe(result => {
        this.course = result;
        console.log(this.course);
      })
    this.golfDataService.GetSelectedCourseTees(this.match.matchCourseId)
      .pipe(takeUntil(this.onDestroy))
      .subscribe(result => {
        this.tees = result;
        console.log(this.tees);
        for (var i = 0; i < this.tees.length; i++) {
          this.golfDataService.GetHoles(this.tees[i].teeIdKey)
            .subscribe(result => {
              console.log(this.teeHoleInfo);
              this.teeHoleInfo.push(result);
              console.log(this.match);
            })
        }
      })
  })

【问题讨论】:

    标签: angular google-cloud-firestore rxjs


    【解决方案1】:

    一般来说,RxJS 的“方式”是尽量保持你的管道尽可能纯净(没有外部副作用)。当然,您可以使用tap 来设置您的全局变量,但我认为在测试、模块化和扩展能力方面最好不要做任何事情,直到您检索到所有数据.

    这种方法构建了一个形式的对象:

    {
      match: any,
      course: any, 
      tees: any[],
      holes: any[]
    }
    
    • ma​​tch 是来自golfDataService.GetSelectedMatch 的结果
    • 课程golfDataService.GetSelectedGolfCourse的结果
    • teesgolfDataService.GetSelectedCourseTees 的结果
    • holes 是对golfDataService.GetHoles 的大量调用的合并结果(tees 中的每个条目都应该调用golfDataService.GetHoles

    最终结果被订阅,然后所有控制台和对全局变量的赋值都会被调用。

    this.myMatch = this.route.snapshot.paramMap.get("createdMatchIdKey");
    
    this.golfDataService.GetSelectedMatch(this.myMatch).pipe(
      mergeMap(match =>
        zip(
          this.golfDataService.GetSelectedGolfCourse(match.matchCourseId),
          this.golfDataService.GetSelectedCourseTees(match.matchCourseId)
        ).pipe(
          take(1),
          map(([course, tees])=> ({
            match,
            course,
            tees
          }))
        ),
        mergeMap(({match, course, tees}) => 
          zip(
            ...tees.map(tee => this.golfDataService.GetHoles(tee.teeIdKey))
          ).pipe(
            take(1),
            map(holes => ({
              match,
              course,
              tees,
              holes
            }))
          )
        )
      )
    ).subscribe(({match, course, tees, holes}) => {
      this.match = match;
      this.setupTable(this.match.matchCourseId);
      this.course = course;
      console.log(this.course);
      this.tees = tees;
      console.log(this.tees);
      this.teeHoleInfo = holes;
      console.log(this.teeHoleInfo);
    });
    

    需要注意的一点是 fork(...) 可能比 zip(...).pipe(take(1)) 更好,但它仅在运行 observable 且您确定会完成时才有效。

    【讨论】:

      猜你喜欢
      • 2017-08-10
      • 2021-05-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-24
      • 1970-01-01
      • 2017-08-24
      • 1970-01-01
      相关资源
      最近更新 更多