简体   繁体   English

如何改善Angular组件,以便使用switchMap而不是链接多个订阅?

[英]How can I improve my Angular component so that I am using switchMap instead of chaining multiple subscriptions?

I'm making use of RxJS and observables within my Angular application to process the results of API calls and process data. 我在Angular应用程序中使用RxJS和Observables处理API调用的结果和处理数据。 I've written the component and it works without any issues. 我已经编写了该组件,它可以正常工作。 However after further research into RxJS and observables I've became aware that the way in which I am using subscriptions is considered bad practice. 但是,在对RxJS和Observables进行了进一步研究之后,我意识到我使用订阅的方式被认为是不好的做法。

Essentially I have a function that subscribes to an observable, then inside the subscription a second function is called which doesn't make use of the data from the first subscription, but subscribes to a separate observable to track the state of a particular variable. 本质上,我有一个订阅可观察对象的函数,然后在订阅内部调用了第二个函数,该函数不利用第一个订阅中的数据,而是订阅一个单独的可观察对象以跟踪特定变量的状态。 Then within the same function a third method is called which does make use of data passed from the first subscription and uses it to make an API call and return some data. 然后在同一个函数中调用第三个方法,该方法使用从第一个订阅传递的数据,并使用它进行API调用并返回一些数据。

What I want to do is refactor this code so that the same behaviour occurs but so that I am making use of switchMap or other RxJS functions so that the bad practice within my code is removed. 我想做的就是重构此代码,以便发生相同的行为,但是我正在使用switchMap或其他RxJS函数,从而消除了代码中的不良做法。 However I am unsure as to how I should be employing the use of switchMap etc. 但是我不确定应该如何使用switchMap等。

I'll post my code below with each function I have described and annotated. 我将在下面用我描述和注释的每个函数发布代码。

initSettings(){
    this.getOrganisations$().subscribe( (res: AdminOrganisation[]) => {  //This is the first subscription that makes a get request to return an array of AdminOrganisation objects
      this.organisations = res;                                          //this results of this subscription are used to display different input options to the user in the form of
      this.serial = this.organisations[0].serialRef;                     //a mat-list.
      this.currentOrganisationName = this.organisations[0].serialName;
      this.buildSettingsForm(this.serial);
    });
  }

  buildSettingsForm(serial: string) {
    this.ipRangeFormGroup = this.formBuilder.group(
        {
          ipRanges: this.formBuilder.array([])
        }
    );

    this.numArrayElements = this.ipRangeFormArray.length;

    this.ipRangeFormArray.valueChanges.subscribe(changes => {           //This is the second subscription, this one does not require any external inputs but does rely on the 
      this.numArrayElements = this.ipRangeFormArray.length;             //this.ipRangeFormArray being instantiated before it can be called, therefore it has to be create 
    });                                                                 //syncronously and after the first subscription has recieved and utilised data.

    this.setSettings(serial);
  }

  setSettings(serial: string) {                                                     //This is the third subscription, this subscription utilises the this.serial variable that
    this.getSettingsFromSerial$(serial).subscribe(val => {                          //is retrieved by the first subscription and therefore relies on the data from the first
      this.savedSettingsState = val;                                                //observable to function. Like the second sub, this one also needs to occur after the first
      this.ipRestrictionEnabled = val.ipRestrictionSettings.ipRestrictionEnabled;   //has processed its data.
      for (const i of val.ipRestrictionSettings.ipRanges) {
        this.addRange(i.startRange, i.endRange, i.label);
      }
      this.displayForm = true;
    });
  }

Once I have a grasp on how I should be utilising switchMap/mergeMap/etc I'll be more confident in making this refactorings and improvements myself. 一旦掌握了如何使用switchMap / mergeMap / etc的知识,我将更有信心自己进行重构和改进。 But since I am relatively new to Angular I'm unsure as to what the best practice is when making use of these functions to prevent chains of subscriptions like what I have below. 但是由于我不是Angular的新手,所以我不确定在使用这些功能来阻止订阅链时的最佳做法是什么,例如我下面的内容。

With the smallest amount of changes, something like this: 更改量最小,如下所示:

initSettings() {
  this.getOrganisations$().pipe(
    switchMap((res: AdminOrganisation[]) => {
      this.organisations = res;
      this.serial = this.organisations[0].serialRef;
      this.currentOrganisationName = this.organisations[0].serialName;
      return this.buildSettingsForm(this.serial);
    })
  ).subscribe();
}

buildSettingsForm(serial: string) {
  this.ipRangeFormGroup = this.formBuilder.group(
    {
      ipRanges: this.formBuilder.array([])
    }
  );

  this.numArrayElements = this.ipRangeFormArray.length;

  return merge(
    this.ipRangeFormArray.valueChanges.pipe(
      tap(_ => {
        this.numArrayElements = this.ipRangeFormArray.length;
      })
    ),
    this.setSettings(serial)
  );
}

setSettings(serial: string) {
  return this.getSettingsFromSerial$(serial).pipe(
    tap(val => {
      this.savedSettingsState = val;
      this.ipRestrictionEnabled = val.ipRestrictionSettings.ipRestrictionEnabled;
      for (const i of val.ipRestrictionSettings.ipRanges) {
        this.addRange(i.startRange, i.endRange, i.label);
      }
      this.displayForm = true;
    })
  );
}

It's only call to this.getOrganisations$, make a switchMap. 仅调用this.getOrganisations $,创建一个switchMap。 inside the switchMap use teh response and add at the end return this.getSettingsFromSerial$. 在switchMap中使用响应并在最后添加return this.getSettingsFromSerial $。 so, in subscribe you has the response of the last observable, some like: -I'm not checked the parenthesis- 因此,在订阅中,您具有最后一个可观察到的响应,例如:-我没有检查括号-

initSettings(){
    this.getOrganisations$().pipe(switchMap((res: AdminOrganisation[]) => {  
      //make something with res
      this.organisations = res;                                          
      this.serial = this.organisations[0].serialRef;                     
      this.currentOrganisationName = this.organisations[0].serialName;
      this.buildSettingsForm(this.serial);
      //but return the last observable
      return this.getSettingsFromSerial$(this.serial)
    }))).subscribe(val => {                          
      this.savedSettingsState = val; 
      this.ipRestrictionEnabled = val.ipRestrictionSettings.ipRestrictionEnabled;   
      for (const i of val.ipRestrictionSettings.ipRanges) {
        this.addRange(i.startRange, i.endRange, i.label);
      }
      this.displayForm = true;
    });
  }
  }

  //buildSettingsFrom dont need any thing but serial, and don't call to 
  //setSettings, that you remove

  buildSettingsForm(serial: string) {
    this.ipRangeFormGroup = this.formBuilder.group(
        {
          ipRanges: this.formBuilder.array([])
        }
    );

    this.numArrayElements = this.ipRangeFormArray.length;

    this.ipRangeFormArray.valueChanges.subscribe(changes => {           
      this.numArrayElements = this.ipRangeFormArray.length;             
    });                                                                 
  }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Angular - 使用 switchMap 改进我的自动完成功能 - Angular - improve my autocomplete with switchMap 如何使用 switchMap 而不是嵌套订阅 - How to use switchMap instead of nested subscriptions Angular中如何使用switchmap避免嵌套订阅? - How to use switchmap to avoid nested subscriptions in Angular? 如何 select 列表的某些元素,以便我可以在我的 angular 组件的 html 中显示它们? - How to select certain elements of a list, so I can show them in my html of my angular component? 如何使用RxJS运算符避免多个嵌套订阅? - How can I avoid multiple nested subscriptions using RxJS operators? 如何使用 angular 在我的组件中使用 datePipe? - how can I use datePipe in my component using angular? Angular 7-我创建的订阅过多吗? - Angular 7 - Am I creating too many subscriptions? 如何在此文件夹中创建Angular全新组件? 为什么我使用Angular CLI获取此错误消息? - How can I create an Angular brand new component into this folder? Why am I obtaining this error message using Angular CLI? 如何在多个 Angular 2 项目之间共享 Angular 2 组件? - How can I share an Angular 2 component between multiple Angular 2 projects? 我已经“进入” Kendo网格后,如何从Angular 2组件访问某些内容 - How do i access something from my Angular 2 component after i am already “in” my Kendo Grid
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM