如何将多个主题合并到可观察对象中并在订阅时发出

How to merge multiple subjects into observable and emit on subscribe

我想将多个主题(fooSubject$barSubject$)合并为一个可观察对象(filterChanged$)和return(初始)值(_foo, _bar), 当我订阅合并的 observable (filterChanged$) 并且其中一个值发生变化时。

我已经使用了 BehaviorSubject(对于两个主题)但是 filterChanged$ 将在订阅时发出两次。如何在不使用 BehaviorSubject 的情况下订阅可观察 filterChanged$ 时立即 return 值(_foo_bar)?

export interface IFilterData {
    foo: string;
    bar: string;
}

@Injectable({
    providedIn: 'root'
})
export class FilterService {
    public foo$: Observable<string>;
    public bar$: Observable<string>;
    public filterChanged$: Observable<IFilterData>;

    private fooSubject$: Subject<string>;
    private barSubject$: Subject<string>;
    private _foo: string;
    private _bar: string;

    constructor() {
        this._foo = 'InitialFoo';
        this._bar = 'InitialBar';

        this.foo$ = this.fooSubject$.asObservable();
        this.bar$ = this.barSubject$.asObservable();

        this.filterChanged$ = merge(this.fooSubject$, this.barSubject$).pipe(
            switchMap(() => {
                return of({
                    foo: this._foo,
                    bar: this._bar
                });
            })
        );
    }

    set foo(value: string) {
        this._foo = value;
        this.fooSubject$.next(value);
    }
    get foo(): string {
        return this._foo;
    }

    set bar(value: string) {
        this._bar = value;
        this.barSubject$.next(value);
    }
    get bar(): string {
        return this._bar;
    }
}

I already used BehaviorSubject (for both subjects) but then filterChanged$ will emit twice on subscribe.

发生这种情况是因为,就像您现在可能订阅的 BehaviorSubject 一样,它将向 新订阅者同步发出其 最新值 .

How can I immediately return the values (_foo, _bar) when subscribe to observable filterChanged$

有一种方法可以实现这一点,但请注意,使用这种方法,BehaviorSubjects 不会存储这些 _foo_bar 值。(有一个以及存储它们的方法)

combineLatest(
  this.fooSubject$.pipe(skip(1), startWith(this._foo)),
  this.barSubject$.pipe(skip(1), startWith(this._bar)),
),.subscribe(/* ... */)

这将等到每个 observable 发射一次,然后在这 2 个 observable 之一发射时发射。

使用

skip(1) 是因为我们不想要 Subjects 当前存储的值,而是 _foo_bar 值。