19

I'd like to ask you for help. I omitted code that I assume is not important. Let's imagine TS file that contains service calls:

// file: someService.ts

@Injectable()
export class SomeService {
     method1(){
         var observable = this.http.get(someUrl)
                          .map((res: Response) =><MyClass[]>res.json());
         return observable;
     }

     method2(){
         // Similar to method1
     }
}

// file: someComponent.ts

Please note, that this.method1observable and method2observable are properly assigned from parent (root) component and their type is Observable.

import {Observable}     from 'rxjs/Observable';

export class SomeClass {
    public m1: Observable<MyClass[]>;
    public m2: Observable<AnotherClass[]>

    ngOnInit() {
        Observable.forkJoin(this.m1,this.m2) //<- ERROR HERE
        .subscribe(data => {
            this.myFunction(data[0], data[1]);
            requestAnimationFrame(this.renderLoop);
        });
    }
}

I get "Uncaught ReferenceError: Observable is not defined". Don't you know what am I doing wrong? I saw some examples where Observable.forkJoin is called inside a service. But what if I want to call it inside a component?

Tomino
  • 5,969
  • 6
  • 38
  • 50

3 Answers3

32

You could try to import this way:

import {Observable} from 'rxjs/Rx';

instead of:

import {Observable} from 'rxjs/Observable';

You should also use an array to provide your observables to the forkJoin method:

ngOnInit() {
        Observable.forkJoin([this.m1,this.m2])
        .subscribe(data => {
            this.myFunction(data[0], data[1]);
            requestAnimationFrame(this.renderLoop);
        });
    }

And do not forget to specify inputs in @Component:

@Component({
    inputs: ['m1', 'm2']
})
Tomino
  • 5,969
  • 6
  • 38
  • 50
Thierry Templier
  • 198,364
  • 44
  • 396
  • 360
  • Yes but it's another error ;-) Are you sure that the observables you provide to forkJoin are not null? – Thierry Templier Feb 29 '16 at 13:10
  • Is SomeClass a component? Where / how observable properties are set? – Thierry Templier Feb 29 '16 at 13:12
  • Yes, I'm sure :-) I can do `.subscribe` on each observable and see result. Also google console tells me that they're not null. – Tomino Feb 29 '16 at 13:12
  • SomeClass is a component. Observables are set in parent component: `ngOnInit(){}` – Tomino Feb 29 '16 at 13:15
  • `ngOnInit(){ this.m1 = this._someService.method1(); this.m2 = this._someService.method2(); }` and view definition: `@Component({ template:'' }) ` – Tomino Feb 29 '16 at 13:20
  • Okay make sense! What do you have at line 8533 in the Rx.js file? – Thierry Templier Feb 29 '16 at 13:22
  • source.subscribe(new AllSubscriber(subscriber, i, context)); 1st call: source is Observable, subscriber is Subscriber, context is Object, i = 0 2nd call: source is undefined, subscriber is Subscriber, context is Object, i = 1 – Tomino Feb 29 '16 at 13:28
  • Could you try: Observable.forkJoin([ obs1, obs2 ]); – Thierry Templier Feb 29 '16 at 13:34
  • I think I've already tried this option. Exception remains. BUT, I put breakpoint inside a subscribe(data => ... here ... ) function and I can see, that data variable is filled in properly - data[0] and data[1] contains correct data. – Tomino Feb 29 '16 at 13:40
  • Heh... I think I got it. The second exception belongs to code below (typo mistake). But MAIN reason was that I forgot to specify 2nd Observable (m2) in *@Component { inputs : ['m1', **'m2'**] }* – Tomino Feb 29 '16 at 13:56
5

You should avoid importing the whole rxjs library as it is quite big. If you have the following imports anywhere in your app, you will be importing the whole rxjs, so have that in mind:

import {Observable} from 'rxjs';

or

import {Observable} from 'rxjs/Rx';

You can instead import the individual features that you will be using, for example:

import {Observable} from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/observable/forkJoin';

UPDATE: Starting with rxjs 5.5, the recommended way to import operators is:

import { range } from 'rxjs/observable/range';
import { map, filter, scan } from 'rxjs/operators';

const source$ = range(0, 10);

source$.pipe(
  filter(x => x % 2 === 0),
  map(x => x + x),
  scan((acc, x) => acc + x, 0)
)
.subscribe(x => console.log(x))
Rui Marques
  • 8,567
  • 3
  • 60
  • 91
  • I have set it up like what you have in three lines but still getting error "forkJoin does not exist on type of Observable" I am using webpack – Shinya Koizumi Sep 13 '17 at 22:05
  • It's just typescript throws error "forkJoin does not exist on type of Observable" like this in the visual studio. – Shinya Koizumi Sep 17 '17 at 07:17
  • Sorry don't know how to further help you, for me importing forkJoin is all its needed for that error to go away. – Rui Marques Sep 18 '17 at 07:43
3

you can refer to this link for more information about using forkjoin() method to run multiple concurrent http.get() requests.Here u can get a complete working example.

http://www.metaltoad.com/blog/angular-2-http-observables

Shailesh kala
  • 1,618
  • 18
  • 16
  • You'd get more points if you put an example using it, and not only the link, it's a good link, thank you :) – Roberto Oct 17 '17 at 15:54