我在Angular应用程序中使用RxJS和Observables处理API调用的结果和处理数据。我已经编写了该组件,它可以正常工作。但是,在进一步研究RxJS和Observables之后,我意识到我使用订阅的方式被认为是不好的做法。
基本上,我有一个订阅可观察对象的函数,然后在订阅内部调用了第二个函数,该函数不使用第一个订阅中的数据,而是订阅一个单独的可观察对象以跟踪特定对象的状态变量。然后在同一个函数中调用第三个方法,该方法使用从第一个订阅传递的数据,并使用它进行API调用并返回一些数据。
我要做的是重构此代码,以便发生相同的行为,但是我正在使用switchMap
或其他RxJS函数,从而消除了代码中的不良做法。但是我不确定应该如何使用switchMap等。
我将在下面用我已经描述和注释的每个函数发布代码。
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;
});
}
一旦我掌握了应该如何使用switchMap / mergeMap / etc,我就会更有信心自己进行重构和改进。但是由于我不是Angular的新手,所以我不确定在使用这些功能来阻止订阅链时的最佳做法是什么,例如我下面的内容。
答案 0 :(得分:0)
更改量最小,如下所示:
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;
})
);
}
答案 1 :(得分:0)
仅调用this.getOrganisations $,创建一个switchMap。在switchMap中使用响应并在最后添加return this.getSettingsFromSerial $。因此,在订阅中,您具有最后一个可观察到的响应,例如:-我未检查括号-
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;
});
}