带有加载器逻辑的嵌套订阅反模式

Nested subscriptions anti-pattern with loader logic

我有以下代码,其中我从各种来源提取数据并在完成后设置加载标志。但是目前维护起来比较麻烦。我该如何修复它?

  constructor(
    private courseContentFacade: CourseContentFacade,
    private changeDetectorRef: ChangeDetectorRef
  ) {
    this.courseContentFacade
      .getUnsplashPhotos()
      .pipe(takeUntil(this.ngUnsubscribe))
      .subscribe((unsplashPhotos) => {
        this.unsplashPhotosLoaded = false;
        if (unsplashPhotos) {
          this.parseUnsplashPhotos(unsplashPhotos);
        }
        this.courseContentFacade
          .getPexelsPhotos()
          .pipe(takeUntil(this.ngUnsubscribe))
          .subscribe((pexelsPhotos) => {
            this.unsplashPhotosLoaded = false;
            if (pexelsPhotos) {
              this.parsePexelsPhotos(pexelsPhotos);
            }
            setTimeout(
              () => {
                this.courseMediaItemsLoaded = true;
                this.pexelsPhotosLoaded = true;
                this.unsplashPhotosLoaded = true;
              },
              environment.production ? 2500 : 1000
            );
          });
      });
  }

以下是我可能会如何将其重做为更加惯用的 RxJS。此代码仍然严重依赖全局状态的使用。

您的应用程序作为一个整体对可变全局状态的需求越少,维护和扩展就越容易。对于 RxJS,这是真实的 5 倍到 10 倍。

即便如此,使用高阶运算符(在本例中为 mergeMap)在很大程度上减少了此处创建的嵌套和复杂性:)

constructor(
  private courseContentFacade: CourseContentFacade,
  private changeDetectorRef: ChangeDetectorRef
) {

  this.courseContentFacade.getUnsplashPhotos().pipe(

    tap(_ => this.unsplashPhotosLoaded = false),
    tap(unsplashPhotos => {
      if (unsplashPhotos) {
        this.parseUnsplashPhotos(unsplashPhotos);
      }
    }),

    mergeMap(_ => this.courseContentFacade.getPexelsPhotos()),
    tap(_ => this.pexelsPhotosLoaded = false),
    tap(pexelsPhotos => {
      if(pexelsPhotos) {
        this.parsePexelsPhotos(pexelsPhotos);
      }
    }),

    takeUntil(this.ngUnsubscribe),
    delay(environment.production ? 2500 : 1000)
    

  ).subscribe(_ => {
    this.courseMediaItemsLoaded = true;
    this.pexelsPhotosLoaded = true;
    this.unsplashPhotosLoaded = true;
  });
  
}