Observable next() 回调未触发。

4
我正在尝试实现一个全局加载指示器,可以在整个应用程序中重复使用。我有一个可注入的服务,其中包含show和hide函数:
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 });
    }
}

这是spinner遮罩组件的代码。我将省略有关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();
  }
}

问题:在叠加组件的代码中,我正在订阅服务的可观察loaderState。然而,当我调用show()函数触发可观察对象的next()时,订阅回调没有被触发。
这是我在app.component.ts中调用show()函数的方式:
ngOnInit() {
               this.spinnerOverlayService.show();
}

我可能错过了什么?回调没有触发似乎很奇怪。

以下是在 Stackblitz 中的示例:https://stackblitz.com/edit/angular-7-registration-login-example-2qus3f?file=app%2Fspinner-overlay%2Fspinner-overlay.component.ts

2个回答

4
问题是您在初始化spinner-overlay之前调用了this.spinnerOverlayService.show();Subject不保存以前发出的值,因此除非有新值,否则晚订阅者将得不到任何值。
您可以做的一件事是将Subject更改为BehaviorSubject,它会向新订阅者发出上一个值。
或者,您可以在ngAfterViewInit中调用this.spinnerOverlayService.show();。这样,您就知道spinner-overlay将被初始化并订阅spinnerOverlayService.loaderState
ngAfterViewInit() {
  this.spinnerOverlayService.show();
}

查看示例


2
除了上面的回答,您可以在spinnerOverlayService服务中添加一个状态来检查显示和隐藏,并且还可以有一个主题来订阅是否准备好新值: "最初的回答"
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

demo.


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接