Наблюдаемый обратный вызов next () не запущен - PullRequest
3 голосов
/ 11 марта 2019

Я пытаюсь реализовать глобальный индикатор загрузки, который можно повторно использовать во всем приложении.У меня есть инъекционный сервис, который имеет функции 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 });
    }
}

И это код компонента наложения счетчика.Я исключу подробности о реализации 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 () наблюдаемого, обратный вызов подписки не запускается.

Вот как я вызываю функцию 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

Ответы [ 2 ]

3 голосов
/ 11 марта 2019

Проблема в том, что вы звоните this.spinnerOverlayService.show(); до инициализации spinner-overlay.Subject s не содержат предыдущего выданного значения, поэтому поздние подписчики не получат никакого значения, если только не будет нового значения.

Одна вещь, которую вы можете сделать, это изменить Subject на BehaviorSubject, который излучаетпоследнее значение для новых подписчиков.

Или вы можете позвонить this.spinnerOverlayService.show(); в течение ngAfterViewInit.Таким образом, вы будете знать, что spinner-overlay будет инициализирован и подпишитесь на spinnerOverlayService.loaderState

ngAfterViewInit() {
  this.spinnerOverlayService.show();
}

Проверьте это

2 голосов
/ 11 марта 2019

В дополнение к вышеприведенному ответу у вас может быть состояние в вашем сервисе 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

демо .

...