angular - วิธีหลีกเลี่ยงปัญหานรกของ callback จากการ subscribe ของ RxJs?
ฉันกำลังใช้ Angular RxJs subscribe เพื่อทำการเรียก HttpClient และจากนั้นทำการเรียกอีกครั้งโดยใช้ค่าจากครั้งแรก ในกรณีนี้ มีการเรียกเพื่อรับ address object และจากนั้นฉันทำการเรียกโดยใช้วัตถุนี้ แบบนี้:
@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);
}
);
}
}
}ฉันพยายามหลีกเลี่ยงการใช้หลาย Subscribe มีหลายตัวแบบนี้ในโค้ดของฉัน ฉันต้องการแนวทางแบบ Async/Await เหมือนกับ promises ของ Node.js แต่ใช้ Observables ในระดับ component ฉันไม่ได้คุ้นเคยกับคำสั่ง RxJs มากนัก... มีวิธีที่ดีกว่าในการเรียกหลายคำสั่งและใช้แค่ subscribe และ catch เพียงครั้งเดียวไหม?
คำตอบ #1
ลองอะไรแบบนี้:
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
})
คำตอบ #2
สำหรับ Angular เมื่อใช้ RxJS แนะนำให้ใช้คลาส Observable เพื่อแก้ปัญหา callback hell ใน RxJS คุณสามารถใช้ API Operators ของ Observable เช่น เมธอด switchMap() (ยังมีเมธอดอื่นๆ สำหรับสถานการณ์ต่างๆ เช่น map(), concatMap(), ...) นี่คือตัวอย่างของฉันเกี่ยวกับการใช้เมธอด switchMap():
(1) สถานการณ์ที่ฉันเจอ: ฉันต้องการ subscribe serviceC แต่ serviceC ต้อง subscribe serviceB และ serviceB ต้อง subscribe serviceA
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) ใช้วิธี switchMap() เพื่อปรับโครงสร้างโค้ดให้มีประสิทธิภาพมากขึ้น
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
}
);
โพสต์ดีเกี่ยวกับการจัดการกับปัญหา callback hell
