RxJs 管道图和 if 条件再次发出一个请求

RxJs pipe map and if condition make one request again

我想在angular中实现一个布尔返回方法。我是这样写的

isViewEnabled(id: string): Observable<boolean> {
    const isAppEnabledObs = this.serviceAccessor.isAppEnabled(id, appName);
    const configObs = this.getConfigFromServer(id);
    const isItSharedObs = this.selectionService.getSharingStatus(id);
    return forkJoin([isAppEnabledObs, configObs, isItSharedObs]).pipe(
        map(results => {
        const isAppEnabled = results[0];
        const config = results[1];
        const isItShared = results[2];
        const isToggleEnabled= config ? config.isToggleEnabled: false;
        return !isItShared ? isToggleEnabled : isToggleEnabled && isAppEnabled;
  })
);

}

现在我可以调用 forkJoin 中的所有请求,并且所有请求都会立即解决。通常在我们的应用程序中,大多数时候 isItShared 变量是 false。在此逻辑中,isAppEnabled 变量仅当且仅当 isItShared 变量为 true.

时才能更改条件

我的问题是如何实现此方法,以便仅在 isItShared 变量的计算结果为 true 时才发出 this.serviceAccessor.isAppEnabled(id, appName); 请求。因为大多数时候我不想调用 this.serviceAccessor.isAppEnabled(id, appName); 方法,因为在大多数情况下它会降低应用程序的速度。如果 isItSharedtrue

,我想加倍努力

一种方法是按照您现在的方式在 forkJoin 中执行所有其他检查,但将昂贵的操作移至 iif (docs) 分支.然后检查您的 !isItShared 条件,仅在需要时切换到 isAppEnabled

您可以将 isAppEnabledObs 排除在 forkJoin 之外,并使用 switchMap 到 return 仅在必要时才进行 isAppEnabledObs 调用的可观察对象。

isViewEnabled(id: string): Observable<boolean> {
    const isAppEnabledObs = this.serviceAccessor.isAppEnabled(id, appName);
    const configObs = this.getConfigFromServer(id);
    const isItSharedObs = this.selectionService.getSharingStatus(id);
    
    return forkJoin([configObs, isItSharedObs]).pipe(
        switchMap(([config, isItShared])=> {
            const isToggleEnabled = config ? config.isToggleEnabled: false;

            return !isItShared 
                ? of(isToggleEnabled)
                : isAppEnabledObs.pipe(
                      map(isAppEnabled => isToggleEnabled && isAppEnabled)
                  );
        })
    );
}

switchMap里面,我们需要return一个observable,所以在不需要make的情况下,我们使用ofisToggleEnabled创建observable额外的电话。

当需要调用时,我们只需 return 一个将 isAppEnabledObs 响应映射到所需布尔值的可观察对象。

惯用的解决方案

首先调用您需要的服务,执行一些转换,然后使用其输出调用更多服务。这通常分为多个可观察对象,但可以很容易地作为一个单元完成。

本质上:只有在发现isItShared为真后才调用this.selectionService.getSharingStatus

您会看到现在有 3 个操作(forkJoin -> map -> switchMap)在工作,而不是两个。当然,mapswitchMap 总是可以结合使用,但我建议不要这样做。

随着代码库的增长,将数据转换与订阅逻辑分开可以使您的代码更加简洁(并且更易于重构)。

isViewEnabled(id: string): Observable<boolean> {

  return forkJoin({
    config: this.getConfigFromServer(id),
    isItShared: this.selectionService.getSharingStatus(id)
  }).pipe(

    map(({config, ...rest}) => ({
      isToggleEnabled: config?.isToggleEnabled || false, 
      ...rest
    })),

    switchMap(({isToggleEnabled, isItShared}) => 
      !isItShared ?
      of(isToggleEnabled) :
      this.selectionService.getSharingStatus(id).pipe(
        map(isAppEnabled => isToggleEnabled && isAppEnabled)
      )
    )

  );

}