0

我有一个 Angular 9 应用程序,大部分情况下使用 observables。在一个组件中,我需要:

  1. 获取所有公司(因为它们包含我需要的某些信息)
  2. 然后获取所有响应并映射公司中的一些额外信息(即响应的公司名称)。
  3. 将该列表作为 observabe 返回,该列表使用异步管道在模板中订阅。

为此,我最初有以下代码(似乎有效):

getPopulatedResponses(): Observable<ResponseModel[]> {
    return this.companyFilesStore
      .select(companyFilesSelector)
      .pipe(
        switchMap(companies => {
          return this.getAccessibleResponses(companies);
        })
      )
  }

getAccessibleResponses(accessibleCompanies: CompanyFilesModel[]): Observable<ResponseModel[]> {
    return this.responsesStore
      .select(responsesSelector)
      .pipe(
        map((responses) => {
          return responses?.map((response) => {
            const company = accessibleCompanies?.find(c => c.companyGuid === response.companyId);
            response.companyName = company?.companyName;
            return response;
          }).sort((a, b) => {
            return a.completedDateTime < b.completedDateTime ? 1 : -1;
          })
        })
      )

首先,我不确定 switchMap 是否是正确的运营商,因为如果 companyFilesSelector 正在更新,然后responsesSelector 部分启动,那不会终止先前的订阅吗?

现在我还需要添加对我拥有的过滤器服务的订阅,因此我对 getAccessibleResponses 方法进行了以下更改(这似乎再次起作用,但我觉得它可能更多的是通过运气/良好的连接而不是任何东西别的):

getAccessibleResponses(
    accessibleCompanies: CompanyFilesModel[],
  ): Observable<ResponseModel[]> {
    return this.searchAndFilterService.getFilter()
      .pipe(
        switchMap(filter => {
          return this.responsesStore
            .select(responsesSelector)
            .pipe(
              map((responses) => {
                return responses?.map((response) => {
                  const company = accessibleCompanies?.find(c => c.companyGuid === response.companyId);
                  response.companyName = company?.companyName;
                  return response;
                })
                  ?.filter(r => !r.isArchived)
                  ?.filter(r => !filter?.selectedCompany || r.companyId === filter.selectedCompany.companyId)
                  ?.filter(r => !filter.selectedAssessmentTemplate ||
                    r.assessmentTemplateId === filter.selectedAssessmentTemplate.assessmentTemplateId)
                  .sort((a, b) => {
                    return a.completedDateTime < b.completedDateTime ? 1 : -1;
                  })
              })
            )
        })
      )
  }

我相当有信心这不是最好的,甚至不是正确的方法,但我有点迷茫,很难理解如何实现以下目标:

  1. 首先获取所有公司。
  2. 将可观察到的公司的结果与响应相结合。
  3. 当过滤器改变时(即过滤器服务 observable)过滤 1/2 的结果。

任何帮助或指导将不胜感激。

4

1 回答 1

1

据我所知,您需要使用 3 个主要部分(和) companies,并且每当其中一个部分发生变化(例如发出新值)时,您都希望根据变化重新计算数据。responsesfilter

如果是这种情况,并假设您的应用程序状态保存在单一数据源中,我会这样做:

const companies$ = this.store.select(companyFilesSelector);

const accessibleResponses$ = this.store.select(responsesSelector);

const activeFilter$ = this.store.select(activeFilterSelector);

const data$ = combineLatest(
  companies$,
  accessibleResponses$,
  activeFilter$,
).pipe(
  map(([companies, responses, filter]) => {
    // Logic here...
  })
)

combineLatest在这里使用是因为您想在 3 个部分之一发生变化时计算显示的数据。

因此,如果您的初始状态可能是:

{
 companies: [],
 responses: [],
 activeFitler: null,
}

例如,每当您添加一些新公司时,map将调用提供的函数以根据新公司更新将显示给用户的内容。添加 newresponses或 new时也会发生同样的情况filter


编辑

我可以使用其中的 switchMap 以便没有订阅查看该商店以潜在地节省内存吗?

我认为它不会节省太多内存,因为switchMap它会根据新到达的value提供的 function取消订阅活动的 observable 并创建一个新的。

另外,由于您正在订阅商店,因此第一次数据检索应该同步发生,因为我认为商店是一种BehaviorSubject(例如 NgRx)

于 2020-04-17T15:20:41.237 回答