[英]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.