2

I must admit that I am doing my first steps with Angular2, and I am running into an issue here, which I have some problems understanding. I am using angular2@2.0.0-beta.0, which has a dependency on rxjs@5.0.0-beta.0.

My intention is to make an HTTP request (to a REST service) and allow the response to be sent to multiple subscribers of the returned observable. If I understand the documentation correctly, I can use the publish() function to convert the Observable returned by e.g. the http.post function to a ConnectableObservable, register multiple subsribers by invoking ConnectableObservable.subcribe(...) multiple times and then invoke ConnectableObservable.connect() to actually perform the HTTP request, e.g. like this:

var obs: Observable<Response> = this.http.post(...);
var cobs: ConnectableObservable<Response> = obs.publish();
cobs.subscribe(sub1);
cobs.subscribe(sub2);
cobs.connect();

At least my IDE seam to agree with this and does not show any warnings. Running the code, I do however get the following error:

EXCEPTION: Error during evaluation of "click"
ORIGINAL EXCEPTION: TypeError: obs.publish is not a function

If I examine the obs object in the debugger, only a very small subset of the documented functions are actually available. If I look into the implementation of the Observable class, only a few of the documented functions are indeed implemented. Most of the functions, among them the publish function, are only declared as a function signature without any actual implementation.

Am I doing something obviously wrong here or have I misunderstood completely how to work with RxJS observables?

If it matters, I am building with gulp, using npm to resolve and download dependencies and including rxjs/bundles/Rx.js from my node_modules directory.

jarnbjo
  • 33,923
  • 7
  • 70
  • 94

1 Answers1

6

In fact, I think that using a ConnectableObservable isn't necessary. Here is the test I made and both subscribers are called when the response is received:

var observable =
  this.http.get('https://angular2.apispark.net/v1/companies/')
           .map(res => res.json());

observable.subscribe(
  data => console.log('subscribe #1'));
observable.subscribe(
  data => console.log('subscribe #2'));

Edit

I think that the share operator can fit your needs:

var observable =
  this.http.get('https://angular2.apispark.net/v1/companies/')
           .map(res => res.json()).share();

observable.subscribe(
  data => console.log('subscribe #1'));
observable.subscribe(
  data => console.log('subscribe #2'));

It allows to create a connectable observable (the share method returns an hot observable). In this case, only one HTTP request is executed...

This question could be helpful for you: Hot and shared Observable from an EventEmitter.

Edit1

After some discussions in comments, it appears that the question was about why the follwing error occurs: TypeError: obs.share is not a function and why are almost all of the documented functions not available in the observable returned by the post function.

So the solution was to explicitly import RxJS operators to make them available at runtime.

There are two solutions. Importing per operator:

import 'rxjs/add/operator/map'

Or more generally this if you want to have all available operator methods for observables:

import 'rxjs/Rx';

Hope it helps you, Thierry

Community
  • 1
  • 1
Thierry Templier
  • 198,364
  • 44
  • 396
  • 360
  • That was my first attempt, but if you see the same behaviour as I am, using that code, the actual HTTP request is performed twice - once for each subscriber. That is not what I wanted. – jarnbjo Jan 08 '16 at 13:24
  • 1
    The `share` operator seems to be what you're looking for ;-) With it only one HTTP request is executed... – Thierry Templier Jan 08 '16 at 13:36
  • I am not sure if the `share` operator is strictly what I'm looking for, but the share function is also not implemented: "TypeError: obs.share is not a function" My question is also rather 'why are almost all of the documented functions not available in the observable returned by the post function?'. – jarnbjo Jan 08 '16 at 13:44
  • Really. I don't have your error ("TypeError: obs.share is not a function")... and all my observers received the data. – Thierry Templier Jan 08 '16 at 14:01
  • What conserns me about the share function is that it is not clear to me from the documentation when the HTTP request is actually performed. Most likely, the HTTP request is started when registering the first subscriber. If later subscribers are added after the HTTP request completes, it is not clear from the documentation, if these subscribers are invoked at all. But to repeat myself: My question is not really about the detailed differences between publish and share, but why almost all of the Observable functions are missing in the runtime object. – jarnbjo Jan 08 '16 at 14:26
  • Okay. Perhaps this answer could help you: http://stackoverflow.com/questions/34515173/angular-2-http-get-with-typescript-error-http-get-map-is-not-a-function-in/34515276#34515276. – Thierry Templier Jan 08 '16 at 14:30
  • That was the right direction. Most of the RxJS operators must be imported explicitely to be available at runtime. Care to rewrite your answer, and I'll upvote and accept? – jarnbjo Jan 08 '16 at 15:09