typescript swichMap& combine最新行为

6uxekuva  于 2023-08-08  发布在  TypeScript
关注(0)|答案(2)|浏览(178)

组件模板:

<div *ngIf="isAdditionalInfoAvailable$ | async">section 1</div>
<div *ngIf="isAdditionalInfoAvailable$ | async">section 2</div>

字符串
组件ts代码:

readonly sessionInfo$ = new BehaviourSubject<SessionInfo | null>(null);

readonly files$ = this.sessionInfo$.pipe(
    filter(Boolean),
    switchMap(sessionInfo =>
      this.filesApiService
        .getPublicDocuments(sessionInfo!.conferenceSessionId, { limit: this.filesPreviewLimit })
        .pipe(tap(() => console.log('request')), catchError(() => of(null)))
    )
  );

readonly isAdditionalInfoAvailable$ = combineLatest([this.sessionInfo$, this.files$]).pipe(
    filter(([sessionInfo]) => !!sessionInfo),
    map(([sessionInfo, files]) => !!sessionInfo!.description || !!files?.data?.length)
  );


我在控制台中看到两条“请求”消息。为什么?为什么?
当获取其自身的订阅时,combineLatest可能会订阅参数中的每个项。如果是这样的话,我可以这样做smth(分享添加):

readonly request$ = this.filesApiService
        .getPublicDocuments(sessionInfo!.conferenceSessionId, { limit: this.filesPreviewLimit })
        .pipe(share());

readonly files$ = this.sessionInfo$.pipe(
    filter(Boolean),
    switchMap(sessionInfo => this.request$)
  );


但在本例中,我不知道在getPublicDocuments中的request$中从哪里获取sessionInfo。我觉得把它作为组件类字段保存不好。我也不能使用函数,因为它返回新的Observable
你能描述一下如何治疗这个病例吗?

az31mfrm

az31mfrm1#

您在控制台中得到两个'request',因为每个async管道触发一个单独的订阅。两个人都是被观察者。
combineLatest本身只会在外部触发一个订阅。
快速解决方法是使用对象将*ngIf条件 Package 在外部容器中,并重用它的值。如果不将其 Package 在对象中,当observable发出false时,条件将失败,并且async中的<div> s将永远不会被检查。

<ng-container
  *ngIf="{
    value: (isAdditionalInfoAvailable$ | async)
  } as isAdditionalInfoAvailable"
>
  <div *ngIf="isAdditionalInfoAvailable.value">section 1</div>
  <div *ngIf="isAdditionalInfoAvailable.value">section 2</div>
</ng-container>

字符串

bd1hkmkf

bd1hkmkf2#

尝试在files$管道的末尾使用shareReplay(1)操作符

readonly files$ = this.sessionInfo$.pipe(
    filter(Boolean),
    switchMap(sessionInfo =>
      this.filesApiService
        .getPublicDocuments(sessionInfo!.conferenceSessionId, { limit: this.filesPreviewLimit })
        .pipe(tap(() => console.log('request')), catchError(() => of(null)))
    ),
    shareReplay(1)
  );

字符串
sessionInfo$改变时,它在新的上重写缓存的值。别忘了取消订阅。
不必担心将storageInfo保留为组件字段。你可以把它设置为私有的和只读的,这将帮助你存储你的对象。此外,你可以让它ReplaySibject,然后你不必设置初始值。在这种情况下,您的可观察值将只在存储时才会勾选。Info将是任何适当的值
你也可以将父标签<ng-content>转换成你需要的类型,但是这会在组件类中创建额外的字段

相关问题