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

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

สาธิต.

บทความที่เกี่ยวข้อง