服务无效的组件之间的通信

时间:2018-03-12 08:34:13

标签: angular angular-services angular-changedetection

我正在使用BehaviorSubject类来更新全局通知的数量。 我有2个组件:组件通知显示通知列表,您可以将这些通知设置为已读。 标题组件显示未读取的通知数,以便让用户知道他错过了网站上的内容。 由于有2个不同的组件,我正在使用服务通过它们进行通信。

这里有一些片段:

notification.service.ts

export class NotificationService {
     public notification: BehaviorSubject<Object> = new BehaviorSubject<Object>({});
     public nbNotificationsChange: BehaviorSubject<number>;

constructor(){
     this.nbNotificationsChange = new BehaviorSubject<number>(0);
}

updateNbNotification(value) {
    this.nbNotificationsChange.next(value);
    this.nbNotificationsChange.subscribe(x => console.log(x));
}

getNbNotification(){
    return this.nbNotificationsChange.getValue();
} }

header.component.ts

export class HeaderComponent implements OnInit, DoCheck {
    public notifications: Notification[] = [];
    public nbNotifications: number = 0;


    constructor (public notificationService: NotificationService){
    this.notificationService.nbNotificationsChange.subscribe(value => {
            this.nbNotifications = value;
        });
    }
ngOnInit() {
    this.getNotificationsNotRead();
    this.notificationService.nbNotificationsChange.subscribe(value => {
        this.nbNotifications = value;
    });
}

ngDoCheck(){
    this.nbNotifications = this.notificationService.getNbNotification()
    //console.log("test");
}
getNotificationsNotRead(){
    aNotRelevantFunctionToRetreiveNotification.subscribe(
            this.notifications = //Receive an array of Notifications here with some code
            this.notifications = this.notifications.filter((notif : Notification) => notif.seen == false); // Check if a notification is read or not
            this.notificationService.updateNbNotification(this.notifications.length);
            console.log(this.notifications.length);
    );
}

get nbNotif(): number {
    return this.notificationService.getNbNotification();
} }

notification.component.ts

export class NotificationsComponent implements OnInit {

public notifications: Notification[];

constructor(public notificationService: NotificationService) {}

ngOnInit() {
    this.getAllNotifications();
}

public getAllNotifications() {
    //Receive an array of notifications to display them, passsing this code. We're in the subscribe
    var nbNotifNotRead = this.notifications.filter((notif : Notification) => notif.seen == false).length;
    this.notificationService.updateNbNotification(nbNotifNotRead); //This value is properly set
}
}

问题是,即使在notification.component.ts一侧设置了值,在header.component.ts中检索的值也不是好的,而且是最初的一个,当然不是我想要的。 / p>

有没有人有想法?现在已经在这个问题上挣扎太多了

更新

这是html部分,非常简单:

<span class="SomeCSSClasses" *ngIf="nbNotifications > 0">{{nbNotifications}}</span>

更新2

涉及的模块:

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { HttpModule } from '@angular/http';
/* A lot of imports */

@NgModule({
  imports: [
    CommonModule,
    HttpModule,

  ],
  providers: [
    ApiService,
    CurrencyService,
    /* A lot of services */
    NbNotificationService
    ]
})

export class ServicesModule { }

这是在App.module中导入的原始模块。 我通过这样创建自己的模块:

import { ModuleWithProviders, NgModule, Optional, SkipSelf } from '@angular/core';

import { NbNotificationService } from './nb-notification.service';
@NgModule({
  providers:    [ NbNotificationService ]
})

export class NbNotificationServiceModule {
    constructor (@Optional() @SkipSelf() parentModule: NbNotificationServiceModule) {
        if (parentModule) {
          throw new Error(
            'NbNotificationServiceModule is already loaded. Import it in the AppModule only');
        }
      }

    static forRoot(): ModuleWithProviders {
        return {
          ngModule: NbNotificationServiceModule,
          providers: [
            {provide: NbNotificationService, useValue: 0 }
          ]
        };
      }
}

尝试将此添加到AppModule,但它出现了类似错误:Cannot instantiate cyclic dependency! NbNotificationService ("[ERROR ->]"): in NgModule PagesModule in ./PagesModule@-1:-1

2 个答案:

答案 0 :(得分:2)

如果您的服务是在延迟加载的模块中提供的,并且您需要应用程序范围的单例,则需要实现.forRoot()并在那里提供服务并使用{{AppModule导入模块1}}。

由于DI上下文在创建后无法修改,因此延迟加载的模块为其提供者获取新的上下文,并且只有此模块和作为其一部分加载的其他模块才能看到相同的提供者实例。 MyModule.forRoot,非延迟加载的模块和其他延迟加载的模块将没有或不同的实例。

另见https://angular.io/guide/singleton-services#forroot

答案 1 :(得分:0)

由于您的服务中有通知,为什么不简单地使用getter?

notification.service.ts

notifications: Notification[];

header.component.ts

get totalNotifications() { return this.notificationService.notifications.length; }