Anu Pai
Anu Pai

Reputation: 11

Subscribing for Observable in service angular is not working

I'm working with Rxjs observable in angular component and learning things. I have scenario where i need to pass data from component to service based on some events.

Price.service.ts

export class PriceService{
   private priceUpdate: BehaviorSubject<Object> = new BehaviorSubject({});
   private oldPriceUpdate: BehaviorSubject<Object> = new BehaviorSubject({});
   getPriceUpdate(){
       return this.priceUpdate.asObservable();
   }
  getOldPrice(){
      return this.oldPriceUpdate.asObservable();
  }
}

Above service is used in component to get price update.

Price.component.ts

@Component({
  selector: 'price',
  templateUrl: 'price.component.html',
  styleUrls: ['price.component.css']
})
export class PriceComponent{
    updateIndicator: BehaviorSubject<Object> = new BehaviorSubject({});
  constructor(private priceService:PriceService, private techIndicator:TechnicalIndicatorService){
    this.techIndicator.subscribeUpdateIndicator(this.updateIndicator.asObservable());
    this.priceService.getPriceUpdate().subscribe(
      (newPrice:any) => {
         this.updatePrice(newPrice);
      }
    )
   this.priceService.getOldPriceUpdate().subscribe(
     (oldPrice:any ) => {
        //some business logic
        this.updateIndicator.next({{data: data, ....});
    });
  }
  private updatePrice(newPrice:any){
     //.... some business logic.... 
      this.updateIndicator.next({data: data, ....});
  }
}

After getting new price from PriceService in component I have another service where I'm doing some technical studies. I need to pass data to service, for which I'm using the behaviour subject in component and Service is subscribing to it. (Different from usual approach where component is subscribing.)

Please let me know if its a valid way to use observable.

TechnicalIndicator.service.ts

export class TechnicalIndicatorService{
    subscribeUpdateIndicator(updateIndicator:Observable<Object>){
     updateIndicator.subscribe(
         (obj:any) => {
          // some logic
         });
    }
}

However the subscription is working only once in the TechnicalIndicatorService. For any data update afterwards, its is not triggering the subscription. Please let me know what I'm missing here.

Upvotes: 1

Views: 3431

Answers (2)

Hossein Nazarnejad
Hossein Nazarnejad

Reputation: 1

hello mate you should provide it in the top level module

import { Post } from './../contance/models/posts';
import { Subject } from 'rxjs';
import { Injectable } from '@angular/core';
import { USER, User } from '../contance';
import { usersState } from './states/users.state';
import { deleteFromArray, updateArray } from '../utils/array-utils';

@Injectable({
  providedIn: 'root'
})
export class StoreService {
  state = {
    usersState,
  }
  private Posts = new Subject<Post[]>()
  posts = this.Posts.asObservable()
  constructor() {
  }

  getUser() {
    if (localStorage.getItem(USER)) {
      return JSON.parse(localStorage.getItem(USER)) as User
    }
  }

  public postsActions = {
    fetch: (posts: Post[]) => this.Posts.next(posts),
    delete: (id: number) => deleteFromArray('id', id, this.Posts.observers),
    edit: (object: Post) => updateArray('id', object.id, this.Posts.observers, object, true)
  }
}

you need to provide service in app.module :

/**
 * @license
 * Copyright Akveo. All Rights Reserved.
 * Licensed under the MIT License. See License.txt in the project root for license information.
 */
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { NgModule } from '@angular/core';
import { CoreModule } from './@core/core.module';
import { ThemeModule } from './@theme/theme.module';
import { AppComponent } from './app.component';
import { AppRoutingModule } from './app-routing.module';
import {
  NbChatModule,
  NbDatepickerModule,
  NbDialogModule,
  NbMenuModule,
  NbSidebarModule,
  NbToastrModule,
  NbWindowModule,
} from '@nebular/theme';
import { HttpRequestModule } from './@core/interceptor/http-request.module';
import { StoreService } from './@core/context/store.service';

@NgModule({
  declarations: [AppComponent],
  imports: [
    BrowserModule,
    BrowserAnimationsModule,
    HttpRequestModule,
    AppRoutingModule,
    NbSidebarModule.forRoot(),
    NbMenuModule.forRoot(),
    NbDatepickerModule.forRoot(),
    NbDialogModule.forRoot(),
    NbWindowModule.forRoot(),
    NbToastrModule.forRoot(),
    NbChatModule.forRoot({
      messageGoogleMapKey: 'AIzaSyA_wNuCzia92MAmdLRzmqitRGvCF7wCZPY',
    }),
    CoreModule.forRoot(),
    ThemeModule.forRoot(),
  ],
  providers: [StoreService],
  bootstrap: [AppComponent],
})
export class AppModule {
}

Upvotes: 0

Vamshi
Vamshi

Reputation: 9341

You are having too many Subjects. You can prevent them and make it simpler.

From what you wrote I understand you want to inform TechnicalIndicatorService to do something either of priceUpdate or oldPriceUpdate changes.


Solution 1:

For this you dont need to come to component at all. You can just do this. Directly inject PriceService into TechnicalIndicatorService.

TechnicalIndicatorService:

export class TechnicalIndicatorService{
    constructor(private priceService: PriceService){
       priceService.getPriceUpdate().subscribe(this.doSomething);
       priceService.getOldPrice().subscribe(this.doSomething);
    }
    private doSomething(update){
    }
}

You dont need to write anything in component .


Solution 2:

But you dont want them to be aware of each other and want to do only from Component, then you can do this :

PriceComponent

export class PriceComponent{
   constructor(
       private priceService:PriceService,
       private techIndicator:TechnicalIndicatorService
   ){
       this.techIndicator.subscribeUpdateIndicator(
          return Observable.merge(
             priceService.getPriceUpdate(),
             priceService.getOldPrice()
          );
       );

    }
}

If you still want to use Subjects let me know I will check why they are failing.

Upvotes: 1

Related Questions