当我将主题订阅为可观察时,我无法获取数据(rxJS 5.5.2)

时间:2018-02-06 09:41:12

标签: angular rxjs alert

我发现this great code在我的组件中显示警告但是,自Angular 5.2.0和rxJS 5.5.2以来,我无法收到警报。

我把一些控制台日志放在哪里,以了解问题是什么,但我没有找到它。

我认为问题是关于主题asObservable:我可以订阅它但没有数据。

alert.service.ts

import { Injectable } from '@angular/core';
import { Router, NavigationStart } from '@angular/router';
import { Observable } from 'rxjs';
import { Subject } from 'rxjs/Subject';

import { Alert, AlertType } from '../models/alert';

@Injectable()
export class AlertService {
    private subject = new Subject<Alert>();
    private keepAfterRouteChange = false;

    constructor(private router: Router) {
        // clear alert messages on route change unless 'keepAfterRouteChange' flag is true
        router.events.subscribe(event => {
            if (event instanceof NavigationStart) {
                if (this.keepAfterRouteChange) {
                    // only keep for a single route change
                    this.keepAfterRouteChange = false;
                } else {
                    // clear alert messages
                    this.clear();
                }
            }
        });
    }

    getAlert(): Observable<any> {
        return this.subject.asObservable();
    }

    success(message: string, keepAfterRouteChange = false) {
        this.alert(AlertType.Success, message, keepAfterRouteChange);
    }

    error(message: string, keepAfterRouteChange = false) {
        this.alert(AlertType.Error, message, keepAfterRouteChange);
    }

    info(message: string, keepAfterRouteChange = false) {
        this.alert(AlertType.Info, message, keepAfterRouteChange);
    }

    warn(message: string, keepAfterRouteChange = false) {
        this.alert(AlertType.Warning, message, keepAfterRouteChange);
    }

    alert(type: AlertType, message: string, keepAfterRouteChange = false) {
        // I got my alert here from my component 
        this.keepAfterRouteChange = keepAfterRouteChange;
        this.subject.next(<Alert>{ type: type, message: message });
    }

    clear() {
        // clear alerts
        this.subject.next();
    }
}

alert.component.ts

import { Component, OnInit } from '@angular/core';

import { Alert, AlertType } from '../models/alert';
import { AlertService } from '../services/alert.service';

@Component({
    selector: 'alert',
    templateUrl: '../resources/views/alert.component.html',
    styleUrls: ['../resources/scss/alert.scss'],
})

export class AlertComponent {
    alerts: Alert[] = [];

    constructor(private alertService: AlertService) { }

    ngOnInit() {

         // nothing appens here... no data in my console log
        this.alertService.getAlert().subscribe(data => {
            console.log("data");
            console.log(data);

        })

        this.alertService.getAlert().subscribe((alert: Alert) => {
            if (!alert) {
                // clear alerts when an empty alert is received
                this.alerts = [];
                return;
            }

            // add alert to array
            this.alerts.push(alert);
        });
    }

    removeAlert(alert: Alert) {
        this.alerts = this.alerts.filter(x => x !== alert);
    }

    cssClass(alert: Alert) {
        if (!alert) {
            return;
        }

        // return css class based on alert type
        switch (alert.type) {
            case AlertType.Success:
                return 'alert alert-success';
            case AlertType.Error:
                return 'alert alert-danger';
            case AlertType.Info:
                return 'alert alert-info';
            case AlertType.Warning:
                return 'alert alert-warning';
        }
    }
}

component.ts / component.html(这里没什么特别的)

// in my component.ts    
    ngOnInit() {
        this.alertService.warn("test");
        ....
        }

in my component.html
<alert></alert>
编辑:感谢@ J.D解释,我通过用BehaviorSubject替换主题来解决问题

1 个答案:

答案 0 :(得分:1)

我在component.ts中看到你this.alertService.warn("test");(这会在Subject上调用next(),它通常是顶级组件。并且您在alert.component.ts中订阅,它在组件树中较低。这意味着您稍后订阅 - 这就是没有数据的原因。因此,您要么使用其他主题类型,例如BehaviorSubject:

private subject = new BehaviorSubject<Alert>(yourDefaultAlert);

或者在将值推送到Subject之前订阅。您的服务类是单例,因此所有组件共享相同的实例 - 因此,如果您之前订阅,它将接收数据。