Angular forkJoin 订阅未触发

Angular forkJoin Subscribe not firing

我有几个方法

    getFirstDataBunch() {
        return this.repository.getData(this.parameter).pipe(
            switchMap(
                result => {
                    //Do something with result;
                    return of(true);
                }
            )
        );
    }

然后我在 ngOnInit 上将其称为:

    function ngOnInit(){
        forkJoin(this.getFirstDataBunch(), this.getSecondDataBunch(), this.getThirdDataBunch()).subscribe(
            results => {
                //do stuff with results; 
            }
        );
    }

我可以看到所有的 observables 都被调用了,它们 return 是一个 observable,但是 forkJoin Subscribe 方法从未被调用,据我所知 forkJoin仅当所有可观察对象 return 完成时才会触发,我相信情况确实如此,那么为什么不触发?

我也看到有些人只是追求 combineLatest,但因为这些方法只 return 一次,我真的不需要继续寻找它们的更新。

我会简单地使用您 want/need 的组合运算符并用 take(1).

将其管道化

为什么使用 take() 运算符?

因为采用returns一个Observable,它只发射源Observable发出的第一个X值。我们设定排放量。

示例:

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);

如果你想 100% 确定避免任何可能的内存泄漏,我建议还使用 takeUntil()(因为如果可观察对象从不发出,take(1) 可能由于某种原因永远卡住)

.pipe(take(1), takeUntil(this.destroy$))

作为一般建议,始终将 takeUntil() 作为管道的最后一个参数。

关于什么组合运算符:

forkJoin --> 如您所写,等待所有可观察对象完成,然后从每个对象发出最后一个发出的值(如 Promise.all)。它可以工作,但每个可观察对象都需要完成(不仅仅是发出!)。

zip --> 等待所有 observable 发出,然后将值作为数组发出(按顺序 - 下图)。我可能会用这个。

combineLatest --> 等待所有 observables 发射,发射一次。然后,每当任何输入 Observable 发出一个值时,它都会发出发出的 observable 的新值和其他(没有发出的)最后一次发出的值。当然,这也适用于 take(1)...

您的方法未完成,您应该通过 first() 运算符或 take(1).

手动完成
function ngOnInit(){
        forkJoin(
         this.getFirstDataBunch().pipe(first()), 
         this.getSecondDataBunch().pipe(first()), 
         this.getThirdDataBunch().pipe(first())
        ).subscribe(
            results => {
                //do stuff with results; 
            }
        );
    }