ค้นหาเว็บไซต์

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

บทความที่เกี่ยวข้อง