Marcos J.C Kichel
Marcos J.C Kichel

Reputation: 7219

Rxjs - Can't convert cold observable into a hot one

So I am using Angular 2 and struggling to make an HTTP request observable to be shared across multiple observers. More specifically I would like to share the all the response types, including errors.

I've tried like that:

return this._http.request(new Request(options))
  .map((res: Response) => this.refreshToken(res))
  .share()

and then

this.data.request()
  .map((response: Response) => (new financeiro.FetchCompletedAction(response)))
  .catch((error: any) => {
    console.log('lancamento-effects:');
    return Observable.of(new feedback.HttpRequestFailedAction(["Erro ao inserir lançamento"]))
  })

this code above is suposed to send an error action that ultimately shows an error message on the user screen.

Actually this is happening twice..

enter image description here

Also it gets printed twice on console.

enter image description here

Upvotes: 1

Views: 3038

Answers (2)

corolla
corolla

Reputation: 5656

Make sure every subscriber subscribes to the same hot observable. Every time you call:

return this._http.request(new Request(options))
  .map((res: Response) => this.refreshToken(res))
  .share()

You are creating a new hot observable from a cold observable.

Example assuming the above code is wrapped in a function called foo(): If you do the following, you will create 2 hot observables and 2 http requests:

foo().subscribe(...)
foo().subscribe(...)

Whereas the following will only create a single hot observable (and single http request):

let hotObs = foo();
hotObs.subscribe(...)
hotObs.subscribe(...);

Upvotes: 0

AngularChef
AngularChef

Reputation: 14087

Here's some code (Plunkr):

@Component({
  selector: 'my-app',
  template: `
    <button (click)="subscribe()">Subscribe</button>
  `
})
export class AppComponent {
  obs: Observable<any>;

  constructor(private http: Http) {
    // Create the observable ONCE + Share.
    this.obs = this.http.get('https://httpbin.org/get')
      .do(() => console.log('***SIDE EFFECT***'))
      .mapTo('***RESULT***')
      .share();
  }

  subscribe() {
    // Subscribe to the same observable TWICE.
    this.obs.subscribe(val => console.log('subs1', val));
    this.obs.subscribe(val => console.log('subs2', val));
  }
}

Here's what the console shows:

***SIDE EFFECT***
subs1 ***RESULT***
subs2 ***RESULT***

One side-effect (i.e. HTTP request), two subscriptions.

Is that what you're looking for?

Upvotes: 2

Related Questions