Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RxJS subscription not firing

Tags:

angular

rxjs

Currently learning RxJS. I have an integer selectedCourseIndex within a service that I'd like a separate component to subscribe to.

courses-section.service.ts

private selectedCourseIndex: number = -1; //this number can change from another method
private selectedCourseIndexUpdated = new Subject<number>();

getSelectedCourseUpdateListener(){
    return this.selectedCourseIndexUpdated.asObservable();
}

courses-section.component.ts

  private selectedCourseIndex: number = -1; //Placeholder initial selectedCourseIndex until new one given on init from courses-section service
  private selectedCourseSub: Subscription;

  constructor( public coursesSectionService: CoursesSectionService ){}

  ngOnInit(){
   this.selectedCourseIndex = 
   this.coursesSectionService.getSelectedCourseIndex();
   this.selectedCourseSub = this.coursesSectionService
    .getSelectedCourseUpdateListener()
    .subscribe((selectedCourseIndex: number) => {
      this.selectedCourseIndex = selectedCourseIndex;
      console.log('this fires when subscription updates'); //this never fires once
    });
  }

However, the subscription never fires, either when it initally subscribes or when the integer changes. Whats wrong?

like image 417
Ethernetz Avatar asked Jun 05 '19 23:06

Ethernetz


Video Answer


2 Answers

"Subject" observable does not replay the previous values on subscribe. Your subscription will only fire if you do the following in your service [somehow] -

this.selectedCourseIndexUpdated.next(<your new number>);

To fire subscription on each subscribe [to get the last emitted value] you should use "BehaviorSubject" instead of Subject like -

private selectedCourseIndexUpdated = new BehaviorSubject<number>(0);

BehaviorSubject replay the last emitted value on each subscription. Notice BehaviorSubject constructor takes the default value.

like image 108
user2216584 Avatar answered Sep 28 '22 15:09

user2216584


Correct me if i am wrong,

Your problem: you want the current (or latest) value that an observable has irrespective of whether someone has emitted a value right now or not.

Answer: A Subject or Observable doesn’t have a current value. When a value is emitted, it is passed to subscribers and the observable is done with it. Observable will only come to action when another value is emitted to the subject stream.

If you want to have a current value, use BehaviorSubject which is designed for exactly the purpose you need, it keeps the last emitted value, irrespective of when it was emitted and immediately conveys that to new subscribers.

Note: It also has a method getValue() to get the current value.


another problem you are facing.

Problem: your current code doesn’t seems to work.

Answer: Let me give an example as how i work with Observable -

Courses-action.service.ts

import { Injectable } from ‘@angular/core’;
import { Subject } from ‘rxjs’;

@Injectable()
Export class CoursesActionService {
  Public selectedCourseIndexUpdated = new Subject<any>();
  Public isCourseIndexUpdated$ = this.selectedCourseIndexUpdated.asObservable();

Public announceSelectedCourseIndex(response: any) {
  this.selectedCourseIndexUpdated.next(response);
}

Some random file who emits a value to the subscriber -

this.coursesActionService.announceSelectedCourseIndex(453);

Some random file who listens to the emitted value -

this.coursesActionService.isCourseIndexUpdated$.pipe(takeUntil(this.destroyed$))
.subscribe(res => console.log(‘i have the response’, res));
like image 45
samar taj Shaikh Avatar answered Sep 28 '22 16:09

samar taj Shaikh