使用Observable

时间:2016-12-30 02:05:16

标签: angular rxjs rxjs5

我正在使用另一个Observable的输入过滤Observable - 过滤的输入来自用户。

使用RxJS运算符combineLatest完成过滤。使用这意味着在订阅此流时,在两个源Observable都发出之前不会发出任何值 - 在创建任何用户输入之前,我希望创建的流在创建时发出(不进行任何过滤)。 / p>

我认为我应该使用startWith运算符,因此流在创建时有一个发射,但我无法弄清楚如何从Observable中播种。使用Observable是因为数据来自Firebase,并由FirebaseListObservable处理。

下面是我目前正在做的拼凑版本。

let tagInput = document.getElementById('tags');
let tagExclusionStream = Observable
  .fromEvent(tagInput, 'input')
  .map((e: any) => createsArrayFromInput(e.target.value));

let allTags: Observable<any[]> = getAllTags();

let filteredTags = allTags
  .combineLatest(tagExclusionStream, (tags, tagExclusions) => {
     return tags.filter((tag: any) => tagExclusions.indexOf(tag.$key) == -1)
  });

// I want this to print out without needing the tagExclusionStream to emit first 
filteredTags.subscribe(tags => console.log("Tags:", tags))

请告诉我,如果我的方法完全关闭/我有一个更好的方法,因为我是RxJS的新手。

2 个答案:

答案 0 :(得分:8)

startWith仅使用concat internally

const startValue$ = of('start with this')

concat(startValue$, source$)

或编写您自己的运算符

function startFrom<T, O extends ObservableInput<any>>(start: O): OperatorFunction<T, T | ObservedValueOf<O>> {
  return (source: Observable<T>) => concat(start, source)
}

source$.pipe(
  startFrom(startValue$)
)

确保startValue$完成

source$完成后,新的Observable将切换到startValue$。 所以如果Observable开始是一个长期存在的Observable,例如ReplaySubject,您只需要关心最近的值即可确保输入的Observable完整,例如与take(1)

const { ReplaySubject, concat, of } = rxjs;
const { take } = rxjs.operators;

const source$ = of('source-1', 'source-2')
const replay = new ReplaySubject(1)
replay.next('subject-1')
replay.next('subject-2')

const startWith$ = replay.pipe(take(1)) // <-- take one item and complete
const o$ = concat(startWith$, source$)
o$.subscribe(console.log)
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.5.5/rxjs.umd.min.js" integrity="sha256-85uCh8dPb35sH3WK435rtYUKALbcvEQFC65eg+raeuc=" crossorigin="anonymous"></script>

答案 1 :(得分:3)

我认为这会解决问题:

let filteredTags = allTags
  .combineLatest(tagExclusionStream.startWith(''), (tags, tagExclusions) => {
     return tags.filter((tag: any) => tagExclusions.indexOf(tag.$key) == -1)
  });

或者,如果您在不同的地方使用tagExclusionStream,则可以执行此操作:

let tagExclusionStream = Observable
  .fromEvent(tagInput, 'input')
  .map((e: any) => createsArrayFromInput(e.target.value))
  .startWith('');