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

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 => …);

มักมีประโยชน์ค่อนข้างบ่อยเพื่อเก็บข้อมูลจากหลายขั้นตอนให้อยู่ในขอบเขต เช่น เพื่อรวมเข้าด้วยกัน นี่เป็นสิ่งที่ควรจำอยู่เสมอ: คุณยังสามารถซ้อนกันได้ด้วย