当我订阅一个可观察的主题时,我无法获取数据(rxJS 5.5.2) [英] I can't get data when I subscribe to a subject as observable (rxJS 5.5.2)

查看:87
本文介绍了当我订阅一个可观察的主题时,我无法获取数据(rxJS 5.5.2)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我发现此出色的代码可在我的组件中显示警报,但是,由于Angular 5.2.0和rxJS 5.5.2,我听不到警报。

I found this great code to display alert in my component but, since Angular 5.2.0 and rxJS 5.5.2, I can't get my alerts.

我将控制台日志显示在哪里,以了解问题所在,但我没有找到它。

I put some console log eveywhere to understand what is the problem but I didn't find it.

我认为问题在于主题可观察:我可以订阅它,但是没有数据。

I think the problem is about the subject asObservable : I can subscribe to it but there is no data.

alert.service.ts

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

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 /组件。 html(这里没什么特别的)

component.ts / component.html (nothing special here)

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

in my component.html
<alert></alert>

编辑:由于@JD的解释,我通过用BehaviorSubject替换了主题来解决了这个问题

EDIT : thanks to @J.D explanation, I solved the problem by replacing the subject by a BehaviorSubject

推荐答案

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

I see you this.alertService.warn("test"); (this invokes next() on Subject) in component.ts which is usually a top-level component. And you subscribe in alert.component.ts which is lower in component tree. That means you subscribe later - thats why no data comes. So you either use other Subject type, like BehaviorSubject:

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

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

Or subscribe before you push values into Subject. Your service class is a singleton, so all components share the same instance of it - so if you subscribe before, it will receive data.

这篇关于当我订阅一个可观察的主题时,我无法获取数据(rxJS 5.5.2)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆