I would simply use the combination operator that you want/need and pipe it with a take(1)
.
Why the take()
operator?
Because take returns an Observable that emits only the first X values emitted by the source Observable. We set how many emissions.
Example:
import { of } from 'rxjs';
import { take } from 'rxjs/operators';
//emit 1,2,3,4,5
const source = of(1, 2, 3, 4, 5);
//take the first emitted value then complete
const example = source.pipe(take(1));
//output: 1
const subscribe = example.subscribe(console.log);
//output: 1, 2, 3
const example2 = source.pipe(take(3)).subscribe(console.log);
If you want to be 100% sure to avoid any possible memory leak, I suggest using also takeUntil()
(since take(1) can be stuck forever for some reason, if the observable never emits)
.pipe(take(1), takeUntil(this.destroy$))
As a general suggestion, place always takeUntil()
as the last argument of your pipe.
About what combination operator:
forkJoin
--> as you wrote, waits for all observables to complete and then emits the last emitted value from each (like a Promise.all
). It would work, but each observable needs to complete (not just emit!).
zip
--> waits for all observables to emit, then emit values as an array (in sequence order - picture below). I would probably use this.
combineLatest
--> Waits for all observables to emit, emits once. Then whenever any input Observable emits a value, it emits the new value of the observable that emitted and the last emission of the others (who didn't emit). Sure, that would work too with take(1)
...
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…