【问题标题】:Subscribing to behaviour subject, modifying data & setting value again resulting in infinite loop订阅behaviorsubject,再次修改数据和设置值导致死循环
【发布时间】:2021-05-13 03:11:55
【问题描述】:

我们有一个向导功能,其中我们有一个延迟加载的模块,它有一个父组件和多个子组件。

const routes: Routes = [
  {
    path : '',
    component :  WizardHomeComponent,
    canActivate: [HomeGuard],
    children : [
      {
        path : 'route1',
        component :  C1Component,
        canActivate: [ChildGuard]
      },
      {
        path : 'route2',
        component :  C2Component,
        canActivate: [ChildGuard]
      },
      {
        path : 'route3',
        component :  C3Component,
        canActivate: [ChildGuard]
      }
      {
        path : 'complete',
        component :  CompleteFlowComponent,
        canActivate: [ChildGuard]
      }
    ]
  }
];

HomeGuard 基本上是指服务,如果没有数据,则调用 API,然后我们在服务中设置 Behaviour Subject 值并解析保护。

HomeGuard

return new Observable(observer=> { 
  this.apiService.getAPIResult().subscribe(res=>{
    this.subjectService.setRequestData(res)  // Inside the subject service, setting the value for the behaviour subject
    observer.next(true)
  });
})

这是主题服务的代码

Subject Service 

private requestDataSource : BehaviorSubject<IWizard[]> = new BehaviorSubject<IWizard[]>(null);
public _requestData: Observable<IWizard[]> = this.requestDataSource.asObservable();

get requestData() {
  return this._requestData;
}

setRequestData(state) {
  this.requestDataSource.next(state);
}

现在,我们有了子路由守卫,即 ChildGuard 。它基本上订阅了行为主题并检查条件,从而允许进入子组件。

ChildGuard

return this.subjectService.requestData
  .pipe(
    tap(wizard => {
      activeStep = wizard.filter(x=>x.isActive == true);
      /* Some othe logic for conditions */
    })
  )
  .pipe(
    map(wizard => isAllowed)
  )

现在,在我们的子路由组件中,每当用户遍历时,我都会更新 isActive 属性 & 用于检查的守卫内部。

问题是当用户点击浏览器后退按钮时,行为主题中未设置值并且不允许进入子组件。 为了尝试解决方案,在 WizardHomeComponent 中,我订阅了可观察的 requestData 并尝试再次修改和设置主题,但这会进入无限循环。

WizardHomeComponent
this.subjectService.requestData.subscribe(res=>{
    /* Code to edit the res */
    const modifiedData = this.modificationFunction(res);
    this.subjectService.setRequestData(modifiedData)
});

【问题讨论】:

    标签: angular typescript rxjs behaviorsubject angular-guards


    【解决方案1】:

    你的结构有问题。我认为您的 URL 中应该有一个参数,并从后端获取数据并在服务中设置 requestData。不在组件中。

    但是通过简单的空检查(或任何检查!)您的问题将得到解决。

    this.subjectService.requestData.subscribe(res=>{
        if(!this.checkValidation(res)) {
            /* Code to edit the res */
            const modifiedData = this.modificationFunction(res);
            this.subjectService.setRequestData(modifiedData)
        }
    });
    
    checkValidation(res){
    //check if res is in modifiedData shape
    }
    

    【讨论】:

      【解决方案2】:

      如果您希望它触发一次,您可以尝试以下操作: 它只取第一个发出的值。

      WizardHomeComponent
      this.subjectService.requestData.pipe(
        first(), // Only take the first value emitted
        map(res => this.modificationFunction(res)) /* Code to edit the res */
      ).subscribe(modifiedData =>
        this.subjectService.setRequestData(modifiedData)
      );
      

      【讨论】:

        猜你喜欢
        • 2018-11-02
        • 2020-05-05
        • 1970-01-01
        • 2021-12-25
        • 2014-12-26
        • 1970-01-01
        • 1970-01-01
        • 2020-03-15
        • 1970-01-01
        相关资源
        最近更新 更多