0

I have through many Rxjs links and stackoverflow links but I am not able to figure this one out

I have a http.get() defined in a service. I am trying to emit the observable response in a Behavior subject and then subscribe to it (since behavior subject has advantages of feetching the last emitted stream of data I believe). Here are the service and component code

SearchService.ts

import { ReplaySubject } from 'rxjs/Rx';
import { error } from 'util';
import { Subject } from 'rxjs/Subject';

import { Response } from '@angular/http';

import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';

import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import {Promotion} from './dto/promo.dto';
import { List } from 'immutable';
import {map, filter, reduce, switchMap, tap} from 'rxjs/operators';


@Injectable()
export class SearchService {
   getUrl: String = './../assets/promotionList.json';
   subject: BehaviorSubject<Promotion[]> ; 
   subjectAsObservable;
   stringify  = require('json-stringify-safe');

   someResult;
   constructor(private http: HttpClient) {
   this.subject = new BehaviorSubject<Promotion[]>([]);

   }
    getNextObservable():Observable<Promotion[]>{
      return this.subject.asObservable(); 
    }
    setValueInSubject(){
       this.getPromoList().subscribe(data => {
       this.someResult = data;
       console.log('getting some result', this.someResult);
      });
  this.subject.next(this.someResult);
}


getPromoList(): Observable<Promotion[]>{

  return this.http.get(`${this.getUrl}`).map(data => {
    console.log('raw data', data);

    this.someResult = data;
    console.log('someresults in first method', this.someResult);
    return this.someResult;
    // now the response returned is the actual Promotion response
  });

 }
}

SearchPromoComponent.ts

import { NgxLoggerLevel } from 'ngx-logger';
import { retry } from 'rxjs/operator/retry';
import { Subject } from 'rxjs/Subject';
import { ActivatedRoute } from '@angular/router';
import { setTimeout } from 'timers';


import { Response } from '@angular/http';

import { FormBuilder, FormGroup, FormControl, Validators, 
ReactiveFormsModule } from '@angular/forms';

import { Observable } from 'rxjs/Observable';
import { Subscription } from 'rxjs/Subscription';
import { debounceTime, filter, flatMap, map, switchMap, tap } from 
'rxjs/operators';

import { Promotion } from './../dto/promo.dto';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { SearchService } from './../search.service';
import { AfterViewChecked, AfterViewInit, Component, OnDestroy, OnInit 
 } from '@angular/core';
import { NGXLogger } from 'ngx-logger';

@Component({
  selector: 'app-search-promo',
  templateUrl: './search-promo.component.html',
  styleUrls: ['./search-promo.component.css']
})
export class SearchPromoComponent implements  OnInit{
  searchGroup: FormGroup;
  stringify  =  require('json-stringify-safe');
  someResult: any;
  promoList: Promotion[];
  subsc: Subscription;
   subValue;
  localInput = new FormControl('', Validators.required);
       consumedPromoList: Observable<Promotion[]>;
       loading: Boolean = false;


  compSubscription: Subscription;
  // Use activated route to get the data from
  constructor(private searchService: SearchService, fb: FormBuilder,
     private paramConfig: ActivatedRoute,
     private logger: NGXLogger,
     private subjectPromoService: SubjectPromoService
  ) {
     this.searchGroup = fb.group({
  'localInput': this.localInput
  });

   }

    ngOnInit(){

       // inorder for the subject subscription to work
       // call like this

       this.searchService.setValueInSubject();

       this.subsc = 
       this.searchService.getNextObservable().subscribe(data => 
       console.log('in comp', data));
     }

 }

The logger in comp always comes as undefined and actually the http service returns the values consumed after in comp

Could you kindly help me figuring out how to get the http emitted value from behavior subject

2 Answers 2

3

In your service, move this.subject.next inside subscribe and in component subscribe to that subject

Service:

  setValueInSubject(){
       this.getPromoList().subscribe(data => {
        this.someResult = data;
        console.log('getting some result', this.someResult);
        this.subject.next(this.someResult);
      });
  }

In your component:

 ngOnInit(){

   this.searchService.setValueInSubject();
   this.subsc = 
   this.searchService.subject.subscribe(data => 
   console.log('in comp', data)
   );
 }
Sign up to request clarification or add additional context in comments.

3 Comments

Glad to help you. :-)
@Joey587, what happened any issue from my answer?
no shravan. Seems ashish answer was more relevant to the POC i was developing. Subscribing to both the subject and the method works fine, but seems that making the subject private and using the method to set and subscribe was more secure to what I was trying to implement
1

Please emit under the subscription. this.someResult might not be available when you emit.

setValueInSubject(){
   this.getPromoList().subscribe(data => {
       this.someResult = data;
       console.log('getting some result', this.someResult);
       this.subject.next(this.someResult);
  });
}

In your implementation, it is a Behavior Subject, so on your next get request I believe you should get the data from the previous request, unless this.someResult is getting reset anywhere else other than the subscription.

5 Comments

you are right Ashish. this.someresults is undefined but after sometime , the log is getting printed with the values. So do you want me do the subscription of getPromoList() in the component ?
Yes Ashih, as Sravan mentioned above I should be rather subscribing to the subject directly as well and include the changes of subject.next() inside the subscription. Thank you though :)
@Joey587: I don't think there is any problem with the way you are subscribing the Subject, you are making it an observable, have put that in a method and subscribing to it. That should work fine according to me. Doesn't it?
@Joey587: Then I think it's a good practice to not make the Subject as public. Making it public gives freedom to manipulate the Subject from anywhere else. you don't want that, right? You only want the getter (as Observable) to be public.. Anyone can listen to the changes but can't change the value themseleves..
that makes sense. You are right. Guess yours should be marked as more appropriate answer

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.