javascript - callback ของ Observable next() ไม่ถูกเรียก
ฉันกำลังพยายามสร้างตัวบ่งชี้การโหลดทั่วโลกที่สามารถนำกลับมาใช้ใหม่ได้ในแอปพลิเคชันทั้งหมด ฉันมีเซอร์วิสที่สามารถฉีดเข้าไปได้ซึ่งมีฟังก์ชันแสดงและซ่อน:
import { Injectable } from '@angular/core';
import { Subject } from 'rxjs';
@Injectable()
export class SpinnerOverlayService {
private loaderSubject = new Subject<any>();
public loaderState = this.loaderSubject.asObservable();
constructor() { }
/**
* Show the spinner
*/
show(): void {
this.loaderSubject.next(<any>{ show: true });
}
/**
* Hide the spinner
*/
hide(): void {
this.loaderSubject.next(<any>{ show: false });
}
}
และนี่คือโค้ดของคอมโพเนนต์สปินเนอร์โอเวอร์เลย์ ผมจะงดรายละเอียดเกี่ยวกับการใช้งาน HTML และ CSS เนื่องจากมันไม่สำคัญที่นี่
import { Component, OnInit } from '@angular/core';
import { Subscription } from 'rxjs';
import { SpinnerOverlayService } from '../spinner-overlay.service';
@Component({
selector: 'spinner-overlay',
templateUrl: './spinner-overlay.component.html',
styleUrls: ['./spinner-overlay.component.scss']
})
export class SpinnerOverlayComponent implements OnInit {
show = false;
private _subscription: Subscription;
constructor(private spinnerOverlayService: SpinnerOverlayService) { }
ngOnInit(): void {
this._subscription = this.spinnerOverlayService.loaderState.subscribe((state) => {
console.log("Subscription triggered.");
this.show = state.show;
});
}
ngOnDestroy(): void {
this._subscription.unsubscribe();
}
}
ปัญหา: ในโค้ดของคอมโพเนนต์ overlay ผมกำลังสมัครสมาชิกกับ observable loaderState ของ service อย่างไรก็ตามเมื่อผมเรียกใช้ฟังก์ชัน show() ซึ่งกระตุ้น next() ของ observable callback การสมัครสมาชิกไม่ได้ถูกเรียกใช้งาน
นี่คือวิธีที่ฉันเรียกฟังก์ชัน show() ในไฟล์ app.component.ts:
ngOnInit() {
this.spinnerOverlayService.show();
}
ฉันอาจพลาดอะไรไปหรือเปล่า? ดูแปลกมากที่การเรียกกลับไม่ได้ถูกเรียกใช้งาน
นี่คือตัวอย่างใน Stackblitz: https://stackblitz.com/edit/angular-7-registration-login-example-2qus3f?file=app%2Fspinner-overlay%2Fspinner-overlay.component.ts
คำตอบ #1
ปัญหาคือคุณเรียก this.spinnerOverlayService.show(); ก่อนที่ spinner-overlay จะถูกสร้างขึ้น Subject ไม่เก็บค่าที่ถูกส่งออกมาก่อนหน้านี้ ดังนั้นผู้สมัครสมาชิกที่มาทีหลังจะไม่ได้ค่าจนกว่าจะมีค่ามาใหม่
สิ่งหนึ่งที่คุณสามารถทำได้คือเปลี่ยน Subject เป็น BehaviorSubject ซึ่งจะส่งค่าล่าสุดให้กับผู้สมัครสมาชิกใหม่
หรือคุณสามารถเรียก this.spinnerOverlayService.show(); ภายใน ngAfterViewInit ด้วยวิธีนี้ คุณจะรู้ว่า spinner-overlay จะถูกเริ่มต้นและสมัครสมาชิกกับ spinnerOverlayService.loaderState
ngAfterViewInit() {
this.spinnerOverlayService.show();
}
ลองดูสิ
คำตอบ #2
นอกจากคำตอบข้างต้นแล้ว คุณสามารถมีสถานะในบริการ spinnerOverlayService ของคุณเพื่อตรวจสอบการแสดงหรือซ่อน และยังสามารถมี subject เพื่อติดตามว่ามีค่ามาใหม่พร้อมหรือไม่:
public state = { show: false };
constructor() { }
/**
* Show the spinner
*/
show():void {
this.state = { show: true };
this.loaderSubject.next(<any>{ show: true })
}
/**
* Hide the spinner
*/
hide():void {
this.state = { show: false };
this.loaderSubject.next(<any>{ show: false })
}
และใน ngOnInit ของคุณ:
ngOnInit(): void {
if(this.spinnerOverlayService.state.show){
console.log('Subscription triggeredd.');
};
this._subscription = this.spinnerOverlayService.loaderState.subscribe((state) => {
console.log("Subscription triggered.");
this.show = state.show;
});
}
หรือคุณสามารถใช้:
private loaderSubject = new ReplaySubject(1); // to cache last value
สาธิต.
