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

typescript - Angular/RxJS - มี pipe ของ RxJS สำหรับ stream ที่เริ่มต้นหรือไม่?


ฉันกำลังพยายามสร้างวิธีการในการแสดงและซ่อนหน้าจอการโหลดอย่างไดนามิกเมื่อกำลังแก้ไขสตรีมบางอย่าง

นี่คือโค้ดปัจจุบันของฉัน:

this.requestService
        .get<Checkout>(`check/${orderNumber}`)
        .pipe(
            tap(() => this.startLoading()),  //i think this isnt the right way to use this pipe
            finalize(() => this.endLoading())
        )
        .subscribe(
            data => {
                data.orderNumber = orderNumber
                this.checkout.next(data)
            },
            error => {
                this.notification.warning(error)
            }
        )

ผลลัพธ์ที่คาดหวังคือเมื่อสตรีมของฉันเริ่ม ให้แสดงหน้าจอการโหลดด้วย startLoading() และเมื่อการทำงานเสร็จสิ้น ให้ซ่อนการโหลดโดยใช้ endLoading()

โค้ดที่ฉันกำลังทำงานอยู่:

this.startLoading() //basically calling function before i create the stream

this.requestService
        .get<Checkout>(`check/${orderNumber}`)
        .pipe(                
            finalize(() => this.endLoading())
        )
        .subscribe(
            data => {
                data.orderNumber = orderNumber
                this.checkout.next(data)
            },
            error => {
                this.notification.warning(error)
            }
        )

ฉันกำลังใช้ท่อ tap นี้อย่างถูกต้องหรือไม่? มีท่ออื่นที่จะช่วยแก้ปัญหานี้ได้ดีกว่านี้หรือไม่?

วิธีที่ดีที่สุดในการทำสิ่งนี้โดยใช้ RxJS คืออะไร?

คำตอบ #1

ในตัวอย่างแรกของคุณ ท่อของคุณทำงานหลังจากที่คำขอ http ของคุณเสร็จสิ้นแล้ว

สุดท้ายแล้ว คุณก็แค่เรียก this.startLoading() ก่อนที่คุณจะเริ่มการร้องขอ http

this.startLoading();
this.requestService.get<Checkout>(`check/${orderNumber}`).pipe(
  finalize(() => this.endLoading())
).subscribe(() => {

});

ถ้าคุณ จริงๆ ต้องการเรียก this.startLoading() ใน pipe คุณสามารถเรียกมันได้ก่อนที่คำขอ http จะเริ่มโดยการเริ่มจาก observable ของคุณเอง:

return of(null).pipe(
  tap(() => this.startLoading()),
  concatMap(() => this.requestService.get<Checkout>(`check/${orderNumber}`)),
  finalize(() => this.endLoading())
).subscribe(() => {

});

แต่จริงๆ แล้ว การทำแบบนั้นก็แทบไม่มีความหมายอะไร

ดังนั้นไวยากรณ์ tap ของคุณถูกต้อง เพียงแต่มันไม่ได้ทำงานเมื่อคุณคิดว่ามันควรจะทำงาน

คำตอบ #2

ถ้าคุณต้องการทำเอฟเฟกต์ข้างเคียงกับการสมัครใช้งาน observable ทุกครั้ง คุณสามารถห่อแหล่งข้อมูลด้วย defer() ได้

import { defer } from 'rxjs';

...

defer(() => {
  this.startLoading();
  return this.requestService.get<Checkout>(`check/${orderNumber}`);
}).pipe(
    finalize(() => this.endLoading())
  )
  .subscribe(...);