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

javascript - ดึงค่าที่ส่งกลับจาก observable โดยไม่ต้อง subscribe ในคลาสที่เรียก


ใน TypeScript/Angular โดยปกติคุณจะเรียกใช้ฟังก์ชันที่ส่งค่ากลับเป็น observable และสมัครใช้งานมันในคอมโพเนนต์ดังนี้:

this.productsService.getProduct().subscribe((product) => { this.product = product });

นี่ถือว่าดีเมื่อโค้ดทำงานในคลาสที่จัดการข้อมูล แต่ในความคิดของฉัน สิ่งนี้ไม่ควรถูกจัดการในคอมโพเนนต์ ฉันอาจจะคิดผิด แต่ฉันคิดว่างานของคอมโพเนนต์ควรเป็นการขอและแสดงข้อมูลโดยไม่จัดการว่ามันถูกดึงมาอย่างไร

ในเทมเพลตของแองกูลาร์ คุณสามารถทำสิ่งนี้เพื่อสมัครรับและแสดงผลลัพธ์ของ observable:

<h1>{{ product.title | async }}</h1>

เป็นไปได้ไหมที่จะมีบางอย่างแบบนี้ในคลาสคอมโพเนนต์ของฉัน? คอมโพเนนต์ของฉันจะแสดงฟอร์มและตรวจสอบว่าการป้อนวันที่ถูกต้องหรือไม่หลังจากใส่ค่า การส่งฟอร์มจะถูกบล็อกจนกว่าค่าจะถูกต้อง และฉันต้องการเก็บตรรกะทั้งหมดเบื้องหลังในเซอร์วิสซึ่งควรสมัครรับการเรียก AJAX ส่วนคอมโพเนนต์จะตรวจสอบเพียงว่ามีวันที่ถูกต้องหรือไม่

 class FormComponent {
    datechangeCallback(date) {
        this.dateIsValid$ = this.dateService.checkDate(date);
    }

    submit() {
        if (this.dateIsValid$ === true) {
            // handle form submission...
        }
    }
}

คำตอบ #1

คุณสามารถแปลง rxjs Observables เป็น ES6 Promises แล้วใช้ไวยากรณ์ async-await เพื่อรับข้อมูลโดยไม่ต้องสมัครสมาชิก observable

บริการ:

export class DateService {
  constructor(private http: HttpClient) {}

  async isDateValid(date): Promise<boolean> {
    let data = await this.http.post(url, date, httpOptions).toPromise();
    let isValid: boolean;
    // perform your validation and logic below and store the result in isValid variable
    return isValid;
  }
}

ส่วนประกอบ:

class FormComponent {
    async datechangeCallback(date) {
        this.dateIsValid = await this.dateService.isDateValid(date);
    }

    submit() {
        if (this.dateIsValid) {
            // handle form submission...
        }
    }
}

ป.ล.:

ถ้านี่เป็นคำขอ HTTP ธรรมดา ซึ่งเสร็จสมบูรณ์เมื่อได้รับค่าหนึ่งค่า การใช้ Promises จะไม่เป็นปัญหา แต่ถ้าตัว observable นี้สร้างสตรีมของค่าต่อเนื่อง การใช้ Promises จะไม่ใช่ทางออกที่ดีที่สุด และคุณจะต้องกลับไปใช้ rxjs observables

คำตอบ #2

วิธีที่สะอาดที่สุดในความคิดเห็นของฉัน ใช้ 7.4.0 < RxJS < 8

import { of, from, tap, firstValueFrom } from 'rxjs';

const asyncFoo = () => {
  return from(
    firstValueFrom(
      of('World').pipe(
        tap((foo) => {
          console.info(foo);
        })
      )
    )
  );
};

asyncFoo();
// Outputs "World" once

asyncFoo().subscribe((foo) => console.info(foo));
// Outputs "World" twice

วิธีที่ "สะอาดที่สุด" คือการมีโรงงาน (ในบริการบางอย่าง) เพื่อสร้างฟังก์ชันที่สามารถสมัครรับได้ตามตัวเลือก... ประมาณนี้:

const buildObs = (obs) => {
  return from(firstValueFrom(obs));
};

const asyncFoo = () => {
  return buildObs(
    of('World').pipe(
      tap((foo) => {
        console.info(foo);
      })
    )
  );
};