5
votes

I am trying to subscribe component to Service Subject to make sure the component subscription run on service emittion.

The problem is subscription hits only first time after that the subscription doesnt hit also the observable return 0 subscription attached second time.

Following is the code:

export class StoreService {
    private storesList : Subject<Array<KeyValue<string>>> = null;

    constructor(private http: Http, private _uService: UserService) {
        this.storesList = new Subject<Array<KeyValue<string>>>();
     }
    loadStores(): void{
        this.getAllStores().subscribe(m=>{
            debugger;
            this.storesList.next(m);
        });
    }
    storeListEvent(): Observable<Array<KeyValue<string>>>{
    return this.storesList.asObservable();
    } 
}

While the component is.

export class HeaderNavComponent implements OnInit, AfterViewInit,OnDestroy  {

    private storeUpdateSubscription = null;    
    constructor(private _userService: UserService, private cdRef: ChangeDetectorRef, private _storeService: StoreService, private router: Router, private location: Location) {

        this.storeUpdateSubscription = this._storeService.storeListEvent().subscribe(stores => {
            debugger;
            this.appStore = stores;
            this.verifySuperAdmin();
        });
    }

Aim to call that the above subscription in component every time

When Store Service - loadStores is called

3
Consider using new ReplaySubject<Array<KeyValue<string>>>(1) to keep the last value until loadStores() provides the next value. This way, new subscribers will always get a value. - Benjamin
you are not destroying component and service anywhere right ? - Pranay Rana
can you provide code at stackbiz - Pranay Rana
@PranayRana yes i am not destroying the component and service too. Component is in the Header Part of the application which will always stay there. - Shan Khan
Where do you call loadStores exactly? - David

3 Answers

6
votes

You are applying an antipattern: NEVER subscribe a service call in the same service. You have to return the call and the component have to subscribe to this Observable.

Any way, since the storeList is a subject, you can simplify doing that:

this.getAllStores().subscribe(this.storesList);

because a subject is an observer aswell

3
votes

Your code is not complete (e.g. there is no getAllStores() or storeListEvent() method, it is not clear what userServicedoes) so what I am going to say may be not correct in your case.

Anyways, the thing I recommend you to do is simplify your logic along these lines

  1. Remove the Subject from StoreService
  2. make loadStores() method return an Observable
  3. In HeaderNavComponent subscribe to the Observable returned by loadStores()
  4. Place the subscription logic in the ngOnInit() method rather than in the constructor

This is how the code could look like

    export class StoreService {

        constructor(private http: Http, private _uService: UserService) {
         }
        loadStores(): Observable<Array<KeyValue<string>>> {
               return this.getAllStores();
        }
    }



    export class HeaderNavComponent implements OnInit, AfterViewInit,OnDestroy  {

        private storeUpdateSubscription = null;    
        constructor(private _userService: UserService, private cdRef: ChangeDetectorRef, private _storeService: StoreService, private router: Router, private location: Location) {}


      ngOnInit() {
            this.storeUpdateSubscription = this._storeService.subscribe(stores => {
                debugger;
                this.appStore = stores;
                this.verifySuperAdmin();
            });
        }
}

ADDITIONAL COMMENTS

I assume that the method getAllStores() of StoreService performs an http call via the Http service you define in the constructor

Looking at your code getAllStores() return an Observable, otherwise you would not be able to subscribe

If this is correct, rather than subscribe to getAllStores() returned Observable just to emit a new value with another Observable (storesList) which HeaderNavComponent subscribes to, you can simply have HeaderNavComponent subscribe to the Observable returned by getAllStores() method

I hope this is more clear now

1
votes

The first I would do here is to call the this.storeList.next(m); not inside another subscription but directly from your function. If that works, then you know that the problem is with your other subscription, not with storesList.