Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angular/30.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Angular 使用ngrx嵌套开关映射的潜在竞争条件_Angular_Typescript_Rxjs_Ngrx_Switchmap - Fatal编程技术网

Angular 使用ngrx嵌套开关映射的潜在竞争条件

Angular 使用ngrx嵌套开关映射的潜在竞争条件,angular,typescript,rxjs,ngrx,switchmap,Angular,Typescript,Rxjs,Ngrx,Switchmap,我有一个Angular 9应用程序,它在很大程度上使用了可观测数据。在一个组件中,我需要: 获取所有公司(因为它们包含我需要的特定信息) 然后获取所有响应并映射公司中的一些额外信息(即响应的公司名称) 将该列表作为使用异步管道在模板中订阅的observabe返回 为此,我最初使用了以下代码(似乎有效): getPopulatedResponses():可观察{ 返回此。公司无文件存储 .选择(公司文件选择器) .烟斗( switchMap(公司=>{ 返回此.getAccessibleRespo

我有一个Angular 9应用程序,它在很大程度上使用了可观测数据。在一个组件中,我需要:

  • 获取所有公司(因为它们包含我需要的特定信息)
  • 然后获取所有响应并映射公司中的一些额外信息(即响应的公司名称)
  • 将该列表作为使用异步管道在模板中订阅的observabe返回
  • 为此,我最初使用了以下代码(似乎有效):

    getPopulatedResponses():可观察{
    返回此。公司无文件存储
    .选择(公司文件选择器)
    .烟斗(
    switchMap(公司=>{
    返回此.getAccessibleResponses(公司);
    })
    )
    }
    getAccessibleResponses(accessibleCompanies:CompanyFilesModel[]):可观察{
    返回此文件。ResponseStore
    .选择(响应选择器)
    .烟斗(
    映射((响应)=>{
    返回响应?.map((响应)=>{
    const company=accessibleCompanies?.find(c=>c.companyGuid==response.companyId);
    response.companyName=公司?.companyName;
    返回响应;
    }).排序((a,b)=>{
    返回a.completedDateTime
    首先,我不确定switchMap是否是正确的运算符,因为如果CompanyFileSelector正在更新,然后ResponseSelector以部分方式启动,这不会终止以前的订阅吗

    现在,我还需要向我已经拥有的筛选服务添加订阅,因此我对getAccessibleResponses方法进行了以下更改(该方法似乎仍然有效,但我觉得这可能更多地是因为运气/良好的连接):

    getAccessibleResponses(
    可访问公司:公司文件模型[],
    ):可见{
    返回此.searchAndFilterService.getFilter()
    .烟斗(
    开关映射(过滤器=>{
    返回此文件。ResponseStore
    .选择(响应选择器)
    .烟斗(
    映射((响应)=>{
    返回响应?.map((响应)=>{
    const company=accessibleCompanies?.find(c=>c.companyGuid==response.companyId);
    response.companyName=公司?.companyName;
    返回响应;
    })
    ?.过滤器(r=>!r.isarchive)
    ?.filter(r=>!filter?.selectedCompany | | r.companyId==filter.selectedCompany.companyId)
    ?.filter(r=>!filter.selectedAssessmentTemplate||
    r、 assessmentTemplateId==筛选器。selectedAssessmentTemplate.assessmentTemplateId)
    .排序((a,b)=>{
    返回a.completedDateTime
    我很有信心这不是最好的方法,甚至不是正确的方法,但我有点迷茫,难以理解如何实现以下目标:

  • 首先得到所有的公司
  • 将观察到的公司的结果与回应结合起来
  • 当过滤器发生变化时(即过滤器服务可观察),过滤1/2的结果

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

    据我所知,您有3个主要部分要处理(
    公司
    响应
    过滤器
    ),并且每当这些部分中的一个发生更改(例如,发出新值),您都会根据更改的内容重新计算数据

    如果是这种情况,并假设你的应用程序状态是在一个单一真相来源中进行的,我会这样做:

    const companys$=this.store.select(companyFilesSelector);
    const accessiblereresponses$=this.store.select(responseSelector);
    常量activeFilter$=this.store.select(activeFilterSelector);
    常量数据$=CombineTest(
    公司$,
    可访问响应$,
    activeFilter$,
    ).烟斗(
    映射([公司、响应、过滤器]=>{
    //逻辑在这里。。。
    })
    )
    
    此处使用的是
    CombineTest
    ,因为您希望在三个部分中的一个发生变化时计算显示的数据

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

    {
    公司:[],
    答复:[],
    activeFitler:null,
    }
    
    例如,每当您添加一些新公司时,将调用提供给
    map
    的功能,以便根据新公司更新将向用户显示的内容。添加新的
    响应
    或新的
    过滤器
    时也会发生同样的情况


    编辑 我是否可以使用该存储的开关映射,这样就不会有订阅查看该存储以潜在地节省内存

    我不认为它节省了太多内存,因为
    switchMap
    所做的一切都是基于新到达的值和提供的功能取消订阅活动的可观察对象并创建一个新的可观察对象


    另外,由于您订阅了存储,第一次数据检索应该同步进行,因为我假设存储是一种行为主体(例如NgRx)

    似乎没有异步操作,对吗?因此,理论上,你可以让所有公司和所有响应异步,然后映射两个观察到的结果,以返回完整的对象,但目前它不异步工作,我也不是100%的最佳方式。这就是我正在寻找的。因为公司很少改变我们e从中选择一个切换图,这样就不会有订阅查看该存储以潜在地节省内存?实际上,我需要的可能有点不同,因为在我可以处理响应之前必须加载公司!@BenThomson我已更新了我的答案。“在我可以处理响应之前必须加载公司”嗯,难道所有内容都不符合
    map
    的回调?因为我不会说你正在加载任何东西
    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;
              })
            })
          )
    
    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;
                      })
                  })
                )
            })
          )
      }