Thibs
Thibs

Reputation: 8258

RxJS5 - combineLatest not accessing Angular's local properties

I need to call two http services and one socket. The first http call is to get meta data and set locally one of its values. Then, I need to call the second http service that returns initial values which are updated via a socket afterwards.

This is what I have so far:

export class MyComponent implements OnInit {
    subscription: Subscription;
    title: string;
    prop1: number;
    prop2: number;

    constructor(private http: HttpService,
                private socket: SocketService,
                private route: ActivatedRoute) {
    }

ngOnInit() {
    this.prop1 = this.route.snapshot.parent.params['prop1'];
    this.subscription = this.http.get('/metaData')
        .do(data => {
            this.title = data.title;
            this.prop2 = data.prop2;
        })
        //this.prop2 is undefined in combineLatest...
        .combineLatest(
            this.http.get('initialData', { prop1: this.prop1, prop2: this.prop2 }),
            this.socket.get('updateEvents', { prop1: this.prop1, prop2: this.prop2 }),
            this.updateList)
        .subscribe(data => {
            this.data = data
        })

}       

I believe I am close, but it appears that the combineLatest operator is not accessing local vars as the prop2 is undefined. Is this because I am doing a side effect in the do operator that prop2 is not seen by the combineLatest on time?

Note: If I were to use switchMap, prop2 works, like this:

.switchMap(data => this.http.get('initialData', { prop1: this.prop1, prop2: this.prop2 }))

Why is prop2 undefined when using combineLatest?

Upvotes: 1

Views: 82

Answers (1)

cartant
cartant

Reputation: 58410

It's because the arguments passed to combineLatest are evaluated before combineLatest is called - and, therefore, before the do receives a next notification, etc.

You can use defer to solve the problem:

import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/defer';

// ...

.combineLatest(
    Observable.defer(() => this.http.get('initialData', { prop1: this.prop1, prop2: this.prop2 })),
    Observable.defer(() => this.socket.get('updateEvents', { prop1: this.prop1, prop2: this.prop2 })),
    this.updateList
)

// ...

Upvotes: 1

Related Questions