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);
})
)
);
};
