简体   繁体   English

在RxJS中组合不同类型的Observable,但只发出来自其中一个的值

[英]Combining different kinds of Observables in RxJS but only emitting values coming from one of them

I have a BehaviorSubject, and two EventEmitters. 我有一个BehaviorSubject和两个EventEmitters。 I need to create an Observable that returns the latest value of the BehaviorSubject every time there is a new value emitted by the BehaviorSubject or there is an Event emitted by any of the EventEmitters. 我需要创建一个Observable,每当有一个BehaviorSubject发出的新值或者任何EventEmitters发出一个Event时,它返回BehaviorSubject的最新值。 Basically, I don't care about the value of the event being emitted by the EventEmitters, they should just be a trigger to push out the latest value of the BehaviorSubject. 基本上,我不关心EventEmitters发出的事件的值,它们应该只是一个触发器来推出BehaviorSubject的最新值。

Here is an example: 这是一个例子:

 import Rx from 'rxjs'; import {map} from 'rxjs/operators' import {EventEmitter} from '@angular/core' const bSubject = new Rx.BehaviorSubject('value1'); const emitter1 = new EventEmitter(); const emitter2 = new EventEmitter(); // Should I be using something othere than merge to create the Observable? // Is merge ok but I should be using a special operator? const myOberservable = Rx.merge(bSubject, emitter1, emitter2) myOberservable.subscribe({next: value => console.log(value)}); emitter1.emit('event1'); bSubject.next('value2'); emitter2.emit('event2'); bSubject.next('value3'); /** * It prints: * value1 * event1 * value2 * event2 * value3 * * But I want it to print: * value1 * value1 * value2 * value2 * value3 */ 

Combine merge , withLatestFrom and map . 结合mergewithLatestFrommap BTW I've updated snippet to enable tree-shaking. 顺便说一句,我已经更新了片段以启用树木摇晃。

import { merge, BehaviorSubject } from 'rxjs';
import { withLatestFrom, map } from 'rxjs/operators'
import {EventEmitter} from '@angular/core'

const bSubject = new BehaviorSubject('value1');
const emitter1 = new EventEmitter();
const emitter2 = new EventEmitter();

const merged = merge(bSubject, emitter1, emitter2);
const myOberservable = merged.pipe(withLatestFrom(bSubject), map(x => x[1]));

myOberservable.subscribe({ next: value => console.log(value) });

emitter1.emit('event1');
bSubject.next('value2');
emitter2.emit('event2');
bSubject.next('value3');

Sounds like a perfect case of switchMap . 听起来像是switchMap的完美案例。 I had to use startWith because of the way switchMap works, which only subscribes to the inner Observable once the outer Observable emits a value, therefore you wouldn't actually subscribe to bSubject until emitter1 emits the first value. 由于switchMap工作方式,我不得不使用startWith ,一旦外部Observable发出一个值,它只订阅内部Observable ,因此在emitter1发出第一个值之前你实际上不会订阅bSubject To overcome that, I used startWith which provides an initial value for the Observable . 为了克服这个问题,我使用了startWith ,它为Observable提供了一个初始值。

 import { EventEmitter } from '@angular/core'; import { BehaviorSubject, merge } from 'rxjs'; import { startWith, switchMap } from 'rxjs/operators'; const initialValue = 'value1'; const bSubject = new BehaviorSubject(initialValue); const emitter1 = new EventEmitter(); const emitter2 = new EventEmitter(); const myOberservable = merge(emitter1, emitter2).pipe(switchMap(() => bSubject), startWith(initialValue)); myOberservable.subscribe({next: value => console.log(value)}); emitter1.emit('event1'); bSubject.next('value2'); emitter2.emit('event2'); bSubject.next('value3'); /** * It prints: * value1 * value1 * value2 * value2 * value3 */ 

For further reading, refer to this . 如需进一步阅读,请参阅此处

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM