1

I have an Alert.Service.ts which saves alerts fetched from another service in an array. In another header.component.ts, I want to get the real-time size of that array.

So, in Alert.Service.ts I have

@Injectable()
export class AlertService {

public static alerts: any = [];

// Observable alertItem source
private alertItemSource = new BehaviorSubject<number>(0);
// Observable alertItem stream
public alertItem$ = this.alertItemSource.asObservable();

constructor(private monitorService: MonitorService) {
    if (MonitorService.alertAgg != undefined) {
        AlertService.alerts = MonitorService.alertAgg['alert_list'];
        AlertService.alerts.push({"id":111111,"severity":200}); //add a sample alert

        this.updateAlertListSize(AlertService.alerts.length);

        MonitorService.alertSource.subscribe((result) => {
            this.updateAlertList(result);
        });
    }
}

private updateAlertList(result) {
    AlertService.alerts = result['alert_list'];
    this.updateAlertListSize(AlertService.alerts.length);
}


// service command
updateAlertListSize(number) {
  this.alertItemSource.next(number);
}

And, in header.component.ts, I have

@Component({
selector: 'my-header',
providers: [ AlertService  ],
templateUrl: 'app/layout/header.component.html',
styles: [ require('./header.component.scss')],
})

export class HeaderComponent implements OnInit, OnDestroy {
private subscription:Subscription;
private alertListSize: number;

constructor(private alertSerivce: AlertService) {

}

ngOnInit() {
    this.subscription = this.alertSerivce.alertItem$.subscribe(
        alertListSize => {this.alertListSize = alertListSize;});
}

ngOnDestroy() {
    // prevent memory leak when component is destroyed
    this.subscription.unsubscribe();
}

I expect the alertListSize gets updated as long as the alerts array in Alert.Service.ts changed. However, it's always 0 which is the initial value when the BehaviorSubject is created. It seems that the subscribe part doesn't work.

Bing Lu
  • 3,232
  • 7
  • 30
  • 38
  • If you tried and subscribe directly on `alertItemSource` (and putting it public) is the value correctly returned? – PRacicot Jul 05 '16 at 19:11
  • @PRacicot I've tried that, the value is not updated either. – Bing Lu Jul 05 '16 at 19:16
  • By looking at your code, I see that you `AlertService` constructor has a parameter. But in your `header.component.ts` constructor you have the basic DI. In my current ng2 projects, all my Injectable services have empty constructor. I'd suggest trying to mock a fake `MonitorService` and have an empty constructor see if the BehaviorSubject actually runs and returns the correct value. – PRacicot Jul 05 '16 at 19:53
  • @PRacicot Sorry for the confusing `MonitorService`. It's actually injected in the parent level `app.component.ts`. So, it's accessible inside `Monitor.Service.ts`. After commenting out all `MonitorService` in `AlertService`, the value gets updated. Since `AlertService` depends on the slow `MonitorSerivce`, the `if (MonitorService.alertAgg != undefined)` is false when `AlertService is constructed. – Bing Lu Jul 05 '16 at 20:26
  • @PRacicot Is there a way to force the `AlertService` gets constructed after the `MonitorService` fully prepared? – Bing Lu Jul 05 '16 at 20:31
  • Add a `MonitorService` DI in your `header.component`. Then manually call the constructor of your `AlertService`. Another approach would be @BingLu to have an empty constructor for `AlertService`. Then in the constructor of your `header.component` have both `MonitorService` and `AlertService` injected. Finally in the `ngOnInit() {}` call a new method created in your `AlertService` which will contain your current `MonitorService` constructors logic. – PRacicot Jul 06 '16 at 11:38
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/116567/discussion-between-pracicot-and-bing-lu). – PRacicot Jul 06 '16 at 11:45

1 Answers1

3

You are most likely using the 'providers: [ AlertService ] ' statement in multiple places, and you have two instances of your service. You should only provide your services at the root component, or some common parent component if you want a singleton service. Providers are hierarchical , and providing it at a parent component will make the same instance available to all children.

SlimSim
  • 606
  • 6
  • 15