typescript - การจัดการตัวแปรปิดด้วย RxJS
สถานการณ์ของฉันเป็นดังนี้: - เข้าถึงฐานข้อมูลเพื่อดึงวัตถุบางอย่าง - หลังจากได้วัตถุหลักแล้ว ให้ดึงข้อมูลเพิ่มเติมของมัน - รวมข้อมูลเพิ่มเติมเข้ากับวัตถุหลัก
ฉันต้องการเขียนมันในลักษณะฟังก์ชันบริสุทธิ์ (เช่น ไม่มีผลข้างเคียง) แต่จนถึงตอนนี้ฉันยังไม่สามารถทำได้:
getMeterPointWithMeterDatabyId(id: number, allowEmpty: boolean = false): Observable<MergeObject> {
const params = this.getEmptyParams();
let mp: MergeObject; // This is my enclosed objects I refer to
return this.masterService.getMasterById(params)
.concatMap<MergeObject, MergeData[]>((master: MergeObject) => {
mp = master; // This is side effect generation
return this.meterService.getMasterData(params);
})
.concatMap<MasterData[], MergeObject>((md: MasterData[]) => {
mp.data = md.slice(); // Even more side effects
return Observable.of(mp); // Final result generated form impure result
});
ฉันคิดว่าฉันมีความเข้าใจในระดับดีเกี่ยวกับวิธีการทำงานของ Rx เมื่อไม่มีการพึ่งพากันเป็นวงจรระหว่างวัตถุ (เช่น แถวการเรียกของฉันได้ผลลัพธ์เป็น A -> B -> C) แต่ฉันเริ่มสูญเสียความมั่นใจเมื่อฉันต้องถอยกลับไปยังขั้นตอนการประมวลผลหนึ่งเพื่อดึงข้อมูลก่อนหน้า (เช่น A -> B -> A, ซึ่งในที่สุด A จะมี B อยู่)
แก้ไข: เท่าที่ฉันรู้, ตัวดำเนินการ zip ใช้ได้ผล แต่ฉันอยากรู้ว่า เป็นไปได้ไหมที่จะทำแบบนั้นด้วยตนเอง
คำตอบ #1
ถ้าคุณต้องการวัตถุพื้นฐานจริงๆ เพื่อตรวจสอบรายละเอียด (เช่น การร้องขอต้องเกิดขึ้นต่อเนื่องกัน) คุณสามารถทำได้
this.service.getMaster(id)
.switchMap(master => this.service.getDetails(master)
// .catch(…) <-- if you want to continue even if fetching the details fails
.map(details => merge(master, details))
)
.subscribe();
เคล็ดลับคือเพียงแค่ฝัง map ภายใน switchMap แบบนั้น master จะอยู่ในขอบเขตโดยไม่ต้องทำอะไรซับซ้อน
ถ้าการร้องขอรายละเอียดเป็นอิสระจริง ๆ คุณสามารถเรียกใช้งานทั้งคู่พร้อมกันได้โดยใช้
Observable.forkJoin(
this.service.getMaster(id),
this.service.getDetails(id)
// .catch(…) <-- if you want to continue even if fetching the details fails
)
.map(([master, details) => merge(master, details))
.subscribe();
เทคนิคในการทำให้สายโซ่ของตัวดำเนินการไม่เป็นเชิงเส้น กล่าวคือ การเปลี่ยนรูป
source$
.switchMap(data1 => transformationA(data1))
// From here on out, you only see data1
.switchMap(data2 => transformationB(data2))
// From here on out, you only see data2
.subscribe(data3 => …);
เข้าไปใน
source$
.switchMap(data1 => transformationA(data1)
.switchMap(data2 => transformationB(data2)
// You can see both data1 and data2 here!
)
.subscribe(data3 => …);
มักมีประโยชน์ค่อนข้างบ่อยเพื่อเก็บข้อมูลจากหลายขั้นตอนให้อยู่ในขอบเขต เช่น เพื่อรวมเข้าด้วยกัน นี่เป็นสิ่งที่ควรจำอยู่เสมอ: คุณยังสามารถซ้อนกันได้ด้วย
