1

I have a Subject in my Angular Service like this:

private sub = new Subject();


sendSub(page: page) {
    this.sub.next(page);
}

getSub(): Observable<any> {
    return this.sub.asObservable();
}

In my parent component I have subscribed to getSub(). From my child component I'm sending one next value but in the parent I'm getting two values in subscription.

Need only one value so that my code block executes only once:

subscription: Subscription;

this.subscription = this.pageService
    .getSub()
    .subscribe(
        (data) => {
            this.data = data;
            this.nextSelection();
        }
    );
ng-hobby
  • 2,077
  • 2
  • 13
  • 26
prabas
  • 53
  • 1
  • 1
  • 9
  • Where do you call `this.pageService.getSub().subscribe()`? Provide some context. – frido Sep 25 '20 at 10:14
  • @fridoo The call is in the parent constructor block – prabas Sep 25 '20 at 12:07
  • Your parent component might be created twice. Put a `console.log` in the constructor to check if it's executed twice. – frido Sep 25 '20 at 12:47
  • getSub() is called only once in the application and this is the only instance that consumes the data from the subject. @fridoo – prabas Sep 25 '20 at 15:45
  • Well, if the subscribe next callback is executed twice there can be two reasons for that. Either you subscribe once and the subject emits twice or you subscribe twice and the subject emits once. Do you ever unsubscribe? – frido Sep 25 '20 at 16:37
  • @fridoo Yes, I subscribed once but my subject is emitting twice. I do unsubscribe it onDestroy(). my situation is like I have a set of from in a sequence, the user need to put on to the next form after completing the current form and I send the current page info and get the next in sequence as the subject emits twice the calculation jumps the next form in sequence and lands on the one after – prabas Sep 26 '20 at 13:52

3 Answers3

1

The reason for getting multiple values after the first emit/next of a subject is that you might be subscribing everytime that subject whenever your function gets called.

For e.g.

detail$ = new Subject<UserDetail>();

getUserDetail() {
   detail$.subscribe({ next: res => {} })
}

If you are calling getUserDetail on the button click or any event then the same subject gets subscribed multiple times so the count of observers for that subject is getting increased. So, next time it will emit value to all the observers subscribed till now.

So removed your subscribe code from the place where it can be called multiple times. Either you can put it in constructor or some other place like ngOnInit and just simply next or emit value and that one observer will handle the task that needs to be done.

You can also destroy the subject once you get the next value in this case next time there will be no previous observer.

There is one more method you can use take(1) rxjs operator inside pipe operator, which will take the last value and unsubscribe that subject behalf of you.

Aniket
  • 391
  • 5
  • 13
0

Change

getSub(): Observable<any> {
  return this.sub.asObservable();
} 

to

getSub: Observable<any> = this.sub.asObservable();

This ensures that every subscriber uses the same subject.

  • Thank you. I tried this approach and the result is same. just an info in the above comments I have only one consumer but the value setting is done from multiple locations but only one at any point – prabas Sep 25 '20 at 15:48
0

Add Subscribe code in the constructor of the parent component.Here is a fiddle of the same

this.appService
    .getSub()
    .subscribe(
        (data) => {
             this.data = data;
             this.nextSelection();
        }
    );
Anusha kurra
  • 482
  • 3
  • 9
  • thank you for the response. There is not much diff in my code and suggested as the subscription in my code allows me to easily unsubscribe from the calls. – prabas Sep 26 '20 at 13:55