Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

forkJoin doesn't work with AngularFire2 valueChanges

Please help me to fix an issue I'm struggling.

I have an array of Firebase object keys

const keys = ['-Kx9pqoMWlJLbKLQcAkP', '-Kx9pqoOYlDHTJ64Was5']

What I'm trying to do is to get all those Firebase objects in one stream using forkJoin. Here's what I have:

const obj1 = this.fbService.getObj(keys[0]);
const obj2 = this.fbService.getObj(keys[1]);

forkJoin([obj1, obj2])
    .subscribe(res => {
        console.log(res);  // <-- this never happens
    };

fbService method is:

getObj(key): Observable<MyObj> {
  return this.fb.object(`/path/to/obj/${key}`).valueChanges();
}

I assume that this getObj method doesn't work well with forkJoin, maybe because of valueChanges, am I using it correctly?

However:

  • getObj works fine for getting single Firebase object, like:

    this.fbService.getObj(keys[0])
        .subsribe(res => console.log(res))// <-- works
    
  • forkJoin works fine with simple HTTP requests, like

    const r1 = this.http.get('https://swapi.co/api/people/1');
    forkJoin([r1])
        .subscribe(res => {
            console.log(res);  // <-- works
        };
    

So, what am I doing wrong? My goal is to get array of objects from array of keys:

['-Kx9pqoMWlJLbKLQcAkP', '-Kx9pqoOYlDHTJ64Was5'] => [{prop:'val'},{prop:'val2'}]
like image 542
Ivan Avatar asked Dec 13 '17 09:12

Ivan


People also ask

Does forkJoin run in parallel?

forkJoin accepts a variable number of observables and subscribes to them in parallel. When all of the provided observables complete, forkJoin collects the last emitted value from each and emits them as an array (this is by default, more on this later).

Does forkJoin wait?

forkJoin will wait for all passed observables to emit and complete and then it will emit an array or an object with last values from corresponding observables.

What does ValueChanges return?

The ValueChanges is an event raised by the Angular forms whenever the value of the FormControl, FormGroup or FormArray changes. It returns an observable so that you can subscribe to it. The observable gets the latest value of the control. It allows us to track changes made to the value in real-time and respond to it.


1 Answers

The forkJoin operator requires all source Observables to emit at least one item and to complete.

I don't know much about firebase but I'm suspicious that valueChanges never completes so that's why forkJoin never emits anything. One way to work with this is using take(1) to always complete the chain.

forkJoin(obj1.take(1), obj2.take(1)).subscribe(res => console.log(res);

Maybe in your case it would be better to use zip() operator that just requires all source Observables to emit the same number of items. However make sure you unsubscribe it because it doesn't complete itself until its source Observables complete.

like image 122
martin Avatar answered Sep 17 '22 20:09

martin