代码之家  ›  专栏  ›  技术社区  ›  Nicolas S.

服务不工作时组件之间的通信

  •  1
  • Nicolas S.  · 技术社区  · 6 年前

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

    以下是一些片段:

    通知。服务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();
    } }
    

    标题。组成部分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();
    } }
    

    通知。组成部分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
    }
    }
    

    问题是,即使在通知时设置了该值。组成部分ts侧,在标头中检索的值。组成部分ts不是好的,是最初的,巫婆当然不是我想要的。

    有人有主意吗?已经为此挣扎了太多时间了


    使现代化

    下面是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 { }
    

    这是在应用程序中导入的原始模块。单元 我正在创建自己的模块,如下所示:

    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 回复  |  直到 6 年前
        1
  •  2
  •   Günter Zöchbauer    6 年前

    如果您的服务是在一个延迟加载的模块中提供的,并且您想要一个应用程序范围的单例,那么您需要实现 .forRoot() 并在那里提供服务并在中导入模块 AppModule 具有 MyModule.forRoot

    由于DI上下文在创建后无法修改,因此延迟加载的模块将为其提供程序获取一个新上下文,并且只有此模块和作为其一部分加载的其他模块才能看到相同的提供程序实例。 应用程序模块 ,非延迟加载的模块和其他延迟加载的模块将不会获得任何实例或其他实例。

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

        2
  •  0
  •   user4676340 user4676340    6 年前

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

    通知。服务ts

    notifications: Notification[];
    

    标题。组成部分ts

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