angular - Wie kann man die RxJs subscribe Callback-Hölle vermeiden?
Ich verwende Angular RxJs subscribe, um einen HttpClient-Aufruf zu machen und dann einen weiteren Aufruf mit den Werten des ersten durchzuführen. In diesem Fall gibt es einen Aufruf, um ein Adressobjekt zu erhalten, und dann mache ich einen Aufruf mit diesem Objekt. So:
@Injectable()
export class AddressService {
constructor(private http: HttpClient) { }
getById(addressId: string, userId: string) {
return this.http.get(BACKEND_URL + 'getAddressById/' + [addressId, userId]);
}
}
export class AddressModalComponent implements OnInit {
constructor(private alertService: AlertService, private addressService: AddressService, @Inject(MAT_DIALOG_DATA) public data: any, private dropdownService: DropdownService)
ngOnInit() {
this.addressService.getById(this.data.id, this.data.userId)
.subscribe(
(address: Address) => {
this.dropdownService.getCidadesBrByEstado(address.name)
.subscribe((cities: BrCity[]) => {
this.cities = cities;
this.address = address;
},
error => console.log(error));
}, error => { this.alertService.error(error);
}
);
}
}
}Ich versuche, mehrere Subscribes zu vermeiden, es gibt viele davon in meinem Code. Ich brauche einen Async/Await-Ansatz wie Node.js promises, aber mit Observables auf Komponentenebene. Ich bin mit RxJs-Befehlen nicht sehr vertraut... gibt es einen besseren Weg, viele Aufrufe mit nur einem subscribe und catch zu machen?
Antwort #1
Versuche etwas wie:
import { map, switchMap } from 'rxjs/operators'
this.addressService.getById(this.data.id, this.data.userId).pipe(
switchMap(address => this.dropdownService.getCidadesBrByEstado(address.name).pipe(
// this pass both cities and address to the next observable in this chain
map(cities => ({ cities, address }))
))
).subscribe(({ cities, address }) => {
this.cities = cities
this.address = address
})
Antwort #2
Für Angular empfiehlt es sich, beim Einsatz von RxJS die Observable-Klasse zu verwenden. Um das Callback-Hell in RxJS zu lösen, können Sie die Operators-API von Observable nutzen, wie z. B. die switchMap()-Methode (weitere Methoden für verschiedene Szenarien sind map(), concatMap(), ...). Hier ist mein Beispiel zur Verwendung der switchMap()-Methode:
(1) Situation, die ich hatte: Ich möchte serviceC abonnieren, aber serviceC muss serviceB abonnieren, und serviceB muss serviceA abonnieren
const serviceA(params): Observable<any>;
const serviceB(params): Observable<any>;
const serviceC(params): Observable<any>;
serviceA(paramsA).subscribe(
serviceAResult => {
serviceB(paramsB).subscribe(
serviceBResult => {
serviceC(params).subscribe(
serviceCResult => {
// here is my logic code. Oh, Shit subscribe hell!
}
)
}
)
}
)
(2) Verwenden Sie die switchMap()-Methode, um die Code-Struktur zu optimieren
const serviceB$ = serviceA(paramsA).pipe(
switchMap(serviceAResult => {
return serviceB(paramsB);
})
);
const serviceC$ = serviceB$.pipe(
switchMap(serviceBResult => {
return serviceC(paramsC);
})
);
serviceC$.subscribe(
serviceCResult => {
// here is my logic code.
},
error =>{
// handle error
}
);
Guter Beitrag über den Umgang mit Callback-Hölle.
